├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── README.md ├── dist ├── assets │ ├── icon128.png │ ├── icon16.png │ └── icon48.png ├── background.js ├── content.js ├── hot-reload.js └── manifest.json ├── jest.config.js ├── package.json ├── packages └── colorins │ ├── .circleci │ └── config.yml │ ├── LICENSE │ ├── README.md │ ├── dist │ ├── index.d.ts │ ├── lib │ │ ├── inspector.d.ts │ │ ├── inspector.test.d.ts │ │ ├── paper-project.d.ts │ │ ├── pixel-cell.d.ts │ │ ├── primitive-factory.d.ts │ │ └── utils.d.ts │ ├── main │ │ └── index.js │ └── module │ │ └── index.js │ ├── jest.config.js │ ├── package.json │ ├── src │ ├── index.ts │ └── lib │ │ ├── inspector.test.ts │ │ ├── inspector.ts │ │ ├── paper-project.ts │ │ ├── pixel-cell.ts │ │ ├── primitive-factory.ts │ │ └── utils.ts │ ├── tsconfig.json │ └── yarn.lock ├── src ├── assets │ ├── icon128.png │ ├── icon128.psd │ ├── icon16.png │ ├── icon16.psd │ ├── icon48.png │ └── icon48.psd ├── background.ts ├── common │ ├── content-injector.ts │ ├── index.ts │ ├── inversify.config.ts │ ├── message-service.ts │ ├── models.ts │ └── utils.ts ├── content.ts ├── core │ ├── app-manager.test.ts │ ├── app-manager.ts │ ├── index.ts │ └── store.ts ├── elements │ ├── app.ts │ ├── color-spot.ts │ ├── index.ts │ └── snackbar.ts ├── hot-reload.ts ├── manifest.json ├── popup.html └── popup │ ├── color-context.ts │ ├── components │ ├── alpha-slider.tsx │ ├── app.tsx │ ├── circle-picker.tsx │ ├── dropper.test.tsx │ ├── dropper.tsx │ ├── hue-slider.tsx │ ├── saturation-canvas.test.tsx │ ├── saturation-canvas.tsx │ ├── styled-slider.tsx │ └── value-picker │ │ ├── hex-input.tsx │ │ ├── index.ts │ │ ├── labeled-input.tsx │ │ ├── rgba-input.tsx │ │ └── value-picker.tsx │ ├── constants.ts │ ├── fonts │ ├── icomoon.eot │ ├── icomoon.svg │ ├── icomoon.ttf │ └── icomoon.woff │ ├── index.tsx │ ├── models │ ├── chroma-color.ts │ ├── hsv-color.test.ts │ ├── hsv-color.ts │ └── index.ts │ └── style.css ├── tsconfig.json └── yarn.lock /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | !.eslintrc.js 3 | dist 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: "@typescript-eslint/parser", 4 | env: { 5 | browser: true, 6 | commonjs: true, 7 | node: true, 8 | es6: true, 9 | }, 10 | plugins: ["@typescript-eslint", "import"], 11 | extends: [ 12 | "eslint:recommended", 13 | "plugin:@typescript-eslint/eslint-recommended", 14 | "plugin:@typescript-eslint/recommended", 15 | "plugin:react/recommended", 16 | ], 17 | overrides: [ 18 | { 19 | files: ["*.js*", "*.ts*"], 20 | rules: { 21 | "@typescript-eslint/explicit-function-return-type": "off", 22 | "@typescript-eslint/no-empty-function": "off", 23 | "@typescript-eslint/no-unused-vars": [ 24 | "warn", 25 | { argsIgnorePattern: "^_" }, 26 | ], 27 | }, 28 | }, 29 | ], 30 | rules: { 31 | "comma-dangle": ["warn", "always-multiline"], 32 | semi: ["warn", "always"], 33 | "no-console": ["warn"], 34 | "import/order": [ 35 | "warn", 36 | { 37 | alphabetize: { order: "asc", caseInsensitive: true }, 38 | }, 39 | ], 40 | }, 41 | }; 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_store 2 | node_modules 3 | .cache 4 | *.sw* 5 | **/*.log 6 | coverage 7 | .next 8 | out 9 | .env 10 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: "all", 3 | singleQuote: true, 4 | }; 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Tailwind Color Picker.

2 | 3 |

4 | A chrome extension to pick a pixel from any website and copy the closest tailwind color to it. 5 |

6 |
7 | 8 | ![tailwindcolorpicker](https://user-images.githubusercontent.com/63742054/191900590-9b674703-4795-4003-ae41-753cba581ed5.gif) 9 | 10 |
11 | 12 | ## How to install 13 | 14 | Install the [official Chrome Extension](https://chrome.google.com/webstore/detail/tailwind-color-picker/iaknbjonlhaajcfpfcimahgpfknpihfm) today! 15 | 16 | ## Motivation 17 | 18 | I built this to be used when quickly prototyping something and using other websites for inspiration. Having a color picker to quickly get tailwind colors from other sites helps me move quicker. 19 | 20 | ## How to use it locally 21 | 22 | 1. Run `git clone https://github.com/Nutlope/tailwind-color-picker`. 23 | 2. Go to `chrome://extensions`, enable developer mode at the top right, click "Load Unpacked", then select the dist folder. 24 | 3. Run 'CMD + Shift + X' to toggle the extension, or click it from the toolbar to activate it 25 | 26 | ## How to develop locally 27 | 28 | 1. Run `git clone https://github.com/Nutlope/tailwind-color-picker`. 29 | 2. Run `cd tailwind-color-picker && yarn install` 30 | 3. Run `npm run start` 31 | 32 | ## Credit 33 | 34 | - Uses [any-color](https://github.com/hankchiutw/any-color) for the color picker 35 | - Uses the [nearest-color](https://github.com/dtao/nearest-color) package to calculate the nearest tailwind color 36 | - Uses tailwind colors from [nearestTailwindColor](https://github.com/zhigang1992/nearestTailwindColor/blob/master/colors.js) 37 | -------------------------------------------------------------------------------- /dist/assets/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/dist/assets/icon128.png -------------------------------------------------------------------------------- /dist/assets/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/dist/assets/icon16.png -------------------------------------------------------------------------------- /dist/assets/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/dist/assets/icon48.png -------------------------------------------------------------------------------- /dist/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Tailwind Color Picker", 3 | "short_name": "TailwindColorPicker", 4 | "version": "1.0.0", 5 | "manifest_version": 3, 6 | "description": "Tailwind Color Picker allows you to pick a pixel from any web page and return the closest tailwind color.", 7 | "homepage_url": "https://github.com/nutlope/tailwind-color-picker", 8 | "icons": { 9 | "16": "assets/icon16.png", 10 | "48": "assets/icon48.png", 11 | "128": "assets/icon128.png" 12 | }, 13 | "background": { 14 | "service_worker": "background.js" 15 | }, 16 | "action": { 17 | "default_title": "Click the icon", 18 | "name": "Click to invoke the inspector" 19 | }, 20 | "permissions": ["activeTab", "scripting"], 21 | "commands": { 22 | "toggle-inspector": { 23 | "suggested_key": { 24 | "windows": "Ctrl+Shift+X", 25 | "linux": "Ctrl+Shift+X", 26 | "mac": "Command+Shift+X", 27 | "chromeos": "Ctrl+Shift+X" 28 | }, 29 | "description": "Toggle the inspector" 30 | } 31 | }, 32 | "web_accessible_resources": [ 33 | { 34 | "resources": ["assets/*"], 35 | "matches": [""] 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: "ts-jest/presets/js-with-ts", 3 | setupFiles: ["jest-canvas-mock", "./__mocks__/chrome.ts"], 4 | testEnvironment: "jest-environment-jsdom-sixteen", 5 | transformIgnorePatterns: ["node_modules/(?!(lit-element|lit-html)/)"], 6 | moduleNameMapper: { 7 | "~(.*)": "/src/$1", 8 | }, 9 | globals: { 10 | "ts-jest": { 11 | diagnostics: { 12 | warnOnly: true, 13 | }, 14 | }, 15 | }, 16 | }; 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tailwind-color-picker", 3 | "version": "1.0.1", 4 | "description": "Pick any color from a web page and get the closest tailwind color", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "parcel watch --hmr-hostname localhost src/*.ts* --no-source-maps", 8 | "build": "run-s clean build:colorins build:src", 9 | "build:src": "parcel build src/*.ts* --no-source-maps", 10 | "build:colorins": "yarn workspace colorins build", 11 | "clean": "rm -rf dist", 12 | "postbuild": "cd dist && zip -r tailwind-color-picker_${npm_package_version}.zip *", 13 | "watch": "run-p watch:*", 14 | "watch:src": "parcel watch src/*.ts* --no-source-maps", 15 | "watch:colorins": "yarn workspace colorins watch", 16 | "bump": "HUSKY_SKIP_HOOKS=1 release-it --ci", 17 | "bump:manifest": "sed -i '' \"/\\\"version\\\":/s/\\\"[0-9.]*\\\"/\\\"$npm_package_version\\\"/\" ./src/manifest.json", 18 | "lint": "tsc --noEmit && eslint './src/**/*.{ts,tsx,js,jsx}'", 19 | "lint:fix": "yarn lint --fix && pretty-quick --staged", 20 | "test": "jest" 21 | }, 22 | "private": true, 23 | "workspaces": [ 24 | "packages/colorins" 25 | ], 26 | "staticFiles": { 27 | "staticPath": [ 28 | "src" 29 | ], 30 | "excludeGlob": "**/*.!(json|png)", 31 | "watcherGlob": "**/*.(json|png)" 32 | }, 33 | "lint-staged": { 34 | "*.+(js|jsx|ts|tsx)": [ 35 | "eslint --fix", 36 | "prettier --write", 37 | "bash -c 'tsc --noEmit'" 38 | ] 39 | }, 40 | "author": "Hassan El Mghari", 41 | "license": "MIT", 42 | "devDependencies": { 43 | "@types/chroma-js": "^2.0.0", 44 | "@types/chrome": "^0.0.197", 45 | "@types/jest": "^25.1.4", 46 | "@types/react": "^16.9.25", 47 | "@types/react-dom": "^16.9.5", 48 | "@types/styled-components": "^5.0.1", 49 | "@typescript-eslint/eslint-plugin": "^2.21.0", 50 | "@typescript-eslint/parser": "^2.21.0", 51 | "commitizen": "^4.1.2", 52 | "cz-conventional-changelog": "3.2.0", 53 | "eslint": "^6.8.0", 54 | "eslint-plugin-import": "^2.20.1", 55 | "eslint-plugin-react": "^7.19.0", 56 | "husky": "^4.2.3", 57 | "jest": "^25.1.0", 58 | "jest-canvas-mock": "^2.2.0", 59 | "jest-environment-jsdom-sixteen": "^1.0.3", 60 | "jest-webextension-mock": "^3.5.4", 61 | "lint-staged": "^10.2.6", 62 | "npm-run-all": "^4.1.5", 63 | "parcel-bundler": "^1.12.4", 64 | "parcel-plugin-static-files-copy": "^2.3.1", 65 | "prettier": "^2.0.2", 66 | "pretty-quick": "^2.0.1", 67 | "release-it": "^13.6.1", 68 | "ts-jest": "^25.2.1", 69 | "typescript": "^3.8.3" 70 | }, 71 | "dependencies": { 72 | "@webcomponents/webcomponentsjs": "^2.4.3", 73 | "chroma-js": "^2.1.0", 74 | "inversify": "^5.0.1", 75 | "inversify-inject-decorators": "^3.1.0", 76 | "lit-element": "^2.3.1", 77 | "paper": "^0.12.4", 78 | "react": "^16.13.1", 79 | "react-color": "^2.18.0", 80 | "react-dom": "^16.13.1", 81 | "redux": "^4.0.5", 82 | "reflect-metadata": "^0.1.13", 83 | "styled-components": "^5.0.1", 84 | "nearest-color": "0.4.4" 85 | }, 86 | "config": { 87 | "commitizen": { 88 | "path": "./node_modules/cz-conventional-changelog" 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /packages/colorins/.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # https://circleci.com/docs/2.0/language-javascript/ 2 | version: 2 3 | jobs: 4 | 'node-10': 5 | docker: 6 | - image: circleci/node:10 7 | working_directory: ~/colorins 8 | steps: 9 | - checkout 10 | # Download and cache dependencies 11 | - restore_cache: 12 | keys: 13 | - v1-dependencies-{{ checksum "package.json" }} 14 | # fallback to using the latest cache if no exact match is found 15 | - v1-dependencies- 16 | - run: yarn install 17 | - save_cache: 18 | paths: 19 | - node_modules 20 | key: v1-dependencies-{{ checksum "package.json" }} 21 | - run: yarn test 22 | 'node-latest': 23 | docker: 24 | - image: circleci/node:latest 25 | working_directory: ~/colorins 26 | steps: 27 | - checkout 28 | - restore_cache: 29 | keys: 30 | - v1-dependencies-{{ checksum "package.json" }} 31 | - v1-dependencies- 32 | - run: yarn install 33 | - save_cache: 34 | paths: 35 | - node_modules 36 | key: v1-dependencies-{{ checksum "package.json" }} 37 | - run: yarn test 38 | 39 | workflows: 40 | version: 2 41 | build: 42 | jobs: 43 | - 'node-10' 44 | - 'node-latest' 45 | -------------------------------------------------------------------------------- /packages/colorins/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 hank 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 | -------------------------------------------------------------------------------- /packages/colorins/README.md: -------------------------------------------------------------------------------- 1 | # colorins module 2 | 3 | Image color inspecting widget. 4 | -------------------------------------------------------------------------------- /packages/colorins/dist/index.d.ts: -------------------------------------------------------------------------------- 1 | import { Inspector } from './lib/inspector'; 2 | export * from './lib/inspector'; 3 | export declare const inspectorFactory: (canvas: HTMLCanvasElement) => Inspector; 4 | -------------------------------------------------------------------------------- /packages/colorins/dist/lib/inspector.d.ts: -------------------------------------------------------------------------------- 1 | import { PaperProject } from './paper-project'; 2 | export declare class Inspector { 3 | private project; 4 | onCopy: (_color: string) => void; 5 | private group; 6 | private cells; 7 | private raster; 8 | private get targetCell(); 9 | constructor(project: PaperProject); 10 | loadImage(img: HTMLImageElement): void; 11 | /** 12 | * Update inspector's position. 13 | * 14 | * @remarks 15 | * Update cell colors in the meanwhile if having the rater image. 16 | */ 17 | private moveTo; 18 | /** 19 | * Initialize inspector UI items, including the cursor and circular magnifier. 20 | */ 21 | private initUI; 22 | /** 23 | * Keep inspector's position sync with mouse. 24 | */ 25 | private trackMouse; 26 | /** 27 | * Deal with system copy and snackbar. 28 | */ 29 | private handleColorCopy; 30 | } 31 | -------------------------------------------------------------------------------- /packages/colorins/dist/lib/inspector.test.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /packages/colorins/dist/lib/paper-project.d.ts: -------------------------------------------------------------------------------- 1 | import paper from 'paper'; 2 | export declare class PaperProject extends paper.Project { 3 | } 4 | export declare const paperProjectFactory: (canvas: HTMLCanvasElement) => PaperProject; 5 | -------------------------------------------------------------------------------- /packages/colorins/dist/lib/pixel-cell.d.ts: -------------------------------------------------------------------------------- 1 | export interface PixelCellInit { 2 | pixelAt: paper.Point; 3 | pivot: paper.Point; 4 | size: number; 5 | } 6 | /** 7 | * A class representing a pixel on a paper.Raster. 8 | * 9 | * @remarks 10 | * The cell rectangle is located wthin a coordinate having one unit equalts to `size`. 11 | */ 12 | export declare class PixelCell { 13 | private rect; 14 | static create(init: PixelCellInit): PixelCell; 15 | constructor({ pixelAt, pivot, size }: PixelCellInit); 16 | get raw(): paper.Item; 17 | get position(): paper.Point; 18 | /** 19 | * @remarks 20 | * Color string in hex. 21 | */ 22 | get color(): string; 23 | setColor(paperColor: paper.Color): void; 24 | highlight(): void; 25 | } 26 | -------------------------------------------------------------------------------- /packages/colorins/dist/lib/primitive-factory.d.ts: -------------------------------------------------------------------------------- 1 | export declare function createCursor(): paper.Group; 2 | export declare function createCircleMask({ radius, children }: { 3 | radius: any; 4 | children: any; 5 | }): paper.Group; 6 | -------------------------------------------------------------------------------- /packages/colorins/dist/lib/utils.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper for copying text to system clipboard. 3 | */ 4 | export declare function copy(text: string): boolean; 5 | -------------------------------------------------------------------------------- /packages/colorins/dist/main/index.js: -------------------------------------------------------------------------------- 1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c{}),this.cells=[],this.initUI(),this.trackMouse(),this.handleColorCopy()}get targetCell(){return this.cells[(this.cells.length-1)/2]}loadImage(e){this.project.view.viewSize=new f.default.Size(e.width,e.height);const t=()=>{const t=new f.default.Raster(e);t.position=new f.default.Point(e.width/2,e.height/2),t.width=e.width,t.height=e.height,t.visible=!1,this.raster=t,this.moveTo(this.group.position)};e.complete?t():e.addEventListener("load",t)}moveTo(e){this.group.position=e,this.raster&&this.cells.forEach(e=>{e.setColor(this.raster.getPixel(e.position))})}initUI(){const e=(0,a.createCursor)(),c=e.position.subtract((r-1)/2);for(let a=0;ae.raw)});this.targetCell.highlight(),this.group=new f.default.Group([d,e]),this.group.pivot=new f.default.Point(0,0)}trackMouse(){this.project.view.on("mousemove",({point:e})=>{this.moveTo(e)}),document.body.addEventListener("mouseenter",({clientX:e,clientY:t})=>{this.moveTo(new f.default.Point(e,t))})}handleColorCopy(){this.project.view.on("click",()=>{const f=this.targetCell.color,t=e.from(l)(f);(0,c.copy)(t.name),this.onCopy(f)})}}exports.Inspector=b; 9 | },{"./pixel-cell":"hSxs","./primitive-factory":"XcBK","./utils":"N6d1"}],"QCba":[function(require,module,exports) { 10 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e={inspectorFactory:!0};exports.inspectorFactory=void 0;var r=o(require("paper")),t=require("./lib/inspector");function o(e){return e&&e.__esModule?e:{default:e}}Object.keys(t).forEach(function(r){"default"!==r&&"__esModule"!==r&&(Object.prototype.hasOwnProperty.call(e,r)||Object.defineProperty(exports,r,{enumerable:!0,get:function(){return t[r]}}))});const n=e=>{const o=new r.default.Project(e),n=new t.Inspector(o);return e.style.cursor="none",n};exports.inspectorFactory=n; 11 | },{"./lib/inspector":"kPyX"}]},{},["QCba"], null) -------------------------------------------------------------------------------- /packages/colorins/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest/presets/js-with-ts', 3 | testEnvironment: 'jest-environment-jsdom-sixteen', 4 | setupFiles: ['jest-canvas-mock'], 5 | coverageThreshold: { 6 | global: { 7 | branches: 80, 8 | functions: 80, 9 | lines: 80, 10 | statements: 80, 11 | }, 12 | }, 13 | globals: { 14 | 'ts-jest': { 15 | diagnostics: { 16 | warnOnly: true, 17 | }, 18 | }, 19 | }, 20 | }; 21 | -------------------------------------------------------------------------------- /packages/colorins/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colorins", 3 | "version": "0.1.0", 4 | "description": "Image color inspecting widget", 5 | "main": "dist/main/index.js", 6 | "module": "dist/module/index.js", 7 | "typings": "dist/index.d.ts", 8 | "repository": "https://github.com/hank/colorins", 9 | "license": "MIT", 10 | "keywords": [], 11 | "scripts": { 12 | "describe": "npm-scripts-info", 13 | "watch": "run-p watch:*", 14 | "watch:main": "parcel watch src/*.ts* --no-source-maps --target node -d dist/main", 15 | "watch:module": "parcel watch src/*.ts* --no-source-maps --target browser -d dist/module", 16 | "watch:declaration": "tsc -p tsconfig.json -w", 17 | "build": "run-s clean && run-p build:*", 18 | "build:main": "parcel build src/*.ts* --no-source-maps --target node -d dist/main", 19 | "build:module": "parcel build src/*.ts* --no-source-maps --target browser -d dist/module", 20 | "build:declaration": "tsc -p tsconfig.json", 21 | "lint": "tsc --noEmit && eslint './src/**/*.{ts,tsx,js,jsx}'", 22 | "lint:fix": "yarn lint --fix && pretty-quick --staged", 23 | "test": "jest --coverage", 24 | "bump": "HUSKY_SKIP_HOOKS=1 release-it --ci", 25 | "doc": "run-s doc:html && open-cli build/docs/index.html", 26 | "doc:html": "typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --out build/docs", 27 | "doc:json": "typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --json build/docs/typedoc.json", 28 | "doc:publish": "gh-pages -m \"[ci skip] Updates\" -d build/docs", 29 | "version": "standard-version", 30 | "reset": "git clean -dfx && git reset --hard && npm i", 31 | "clean": "trash build test", 32 | "prepare-release": "run-s reset test cov:check doc:html version doc:publish" 33 | }, 34 | "scripts-info": { 35 | "info": "Display information about the package scripts", 36 | "build": "Clean and rebuild the project", 37 | "fix": "Try to automatically fix any linting problems", 38 | "test": "Lint and unit test the project", 39 | "watch": "Watch and rebuild the project on save, then rerun relevant tests", 40 | "cov": "Rebuild, run tests, then create and open the coverage report", 41 | "doc": "Generate HTML API documentation and open it in a browser", 42 | "doc:json": "Generate API documentation in typedoc JSON format", 43 | "version": "Bump package.json version, update CHANGELOG.md, tag release", 44 | "reset": "Delete all untracked files and reset the repo to the last commit", 45 | "prepare-release": "One-step: clean, build, test, publish docs, and prep a release" 46 | }, 47 | "engines": { 48 | "node": ">=10" 49 | }, 50 | "dependencies": { 51 | "paper": "^0.12.11" 52 | }, 53 | "devDependencies": { 54 | "@bitjson/npm-scripts-info": "^1.0.0", 55 | "@bitjson/typedoc": "^0.15.0-0", 56 | "open-cli": "^5.0.0", 57 | "standard-version": "^8.0.1", 58 | "trash-cli": "^3.0.0" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/colorins/src/index.ts: -------------------------------------------------------------------------------- 1 | import paper from 'paper'; 2 | import { Inspector } from './lib/inspector'; 3 | export * from './lib/inspector'; 4 | 5 | export const inspectorFactory = (canvas: HTMLCanvasElement): Inspector => { 6 | const project = new paper.Project(canvas); 7 | const inspector = new Inspector(project); 8 | canvas.style.cursor = 'none'; 9 | return inspector; 10 | }; 11 | -------------------------------------------------------------------------------- /packages/colorins/src/lib/inspector.test.ts: -------------------------------------------------------------------------------- 1 | import paper from 'paper'; 2 | import { Inspector } from './inspector'; 3 | 4 | describe('Inspector', () => { 5 | it('should create a Inspector instance', () => { 6 | const project = new paper.Project(document.createElement('canvas')); 7 | const inspector = new Inspector(project); 8 | expect(inspector).toBeTruthy(); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /packages/colorins/src/lib/inspector.ts: -------------------------------------------------------------------------------- 1 | import * as nearestColour from 'nearest-color'; 2 | import paper from 'paper'; 3 | import { PaperProject } from './paper-project'; 4 | import { PixelCell } from './pixel-cell'; 5 | import { createCircleMask, createCursor } from './primitive-factory'; 6 | import { copy } from './utils'; 7 | 8 | const kInspectorSize = 11; // should be odd 9 | const kCellSize = 30; 10 | 11 | const colours = { 12 | black: '#000', 13 | white: '#fff', 14 | slate: { 15 | 50: '#f8fafc', 16 | 100: '#f1f5f9', 17 | 200: '#e2e8f0', 18 | 300: '#cbd5e1', 19 | 400: '#94a3b8', 20 | 500: '#64748b', 21 | 600: '#475569', 22 | 700: '#334155', 23 | 800: '#1e293b', 24 | 900: '#0f172a', 25 | }, 26 | gray: { 27 | 50: '#f9fafb', 28 | 100: '#f3f4f6', 29 | 200: '#e5e7eb', 30 | 300: '#d1d5db', 31 | 400: '#9ca3af', 32 | 500: '#6b7280', 33 | 600: '#4b5563', 34 | 700: '#374151', 35 | 800: '#1f2937', 36 | 900: '#111827', 37 | }, 38 | zinc: { 39 | 50: '#fafafa', 40 | 100: '#f4f4f5', 41 | 200: '#e4e4e7', 42 | 300: '#d4d4d8', 43 | 400: '#a1a1aa', 44 | 500: '#71717a', 45 | 600: '#52525b', 46 | 700: '#3f3f46', 47 | 800: '#27272a', 48 | 900: '#18181b', 49 | }, 50 | neutral: { 51 | 50: '#fafafa', 52 | 100: '#f5f5f5', 53 | 200: '#e5e5e5', 54 | 300: '#d4d4d4', 55 | 400: '#a3a3a3', 56 | 500: '#737373', 57 | 600: '#525252', 58 | 700: '#404040', 59 | 800: '#262626', 60 | 900: '#171717', 61 | }, 62 | stone: { 63 | 50: '#fafaf9', 64 | 100: '#f5f5f4', 65 | 200: '#e7e5e4', 66 | 300: '#d6d3d1', 67 | 400: '#a8a29e', 68 | 500: '#78716c', 69 | 600: '#57534e', 70 | 700: '#44403c', 71 | 800: '#292524', 72 | 900: '#1c1917', 73 | }, 74 | red: { 75 | 50: '#fef2f2', 76 | 100: '#fee2e2', 77 | 200: '#fecaca', 78 | 300: '#fca5a5', 79 | 400: '#f87171', 80 | 500: '#ef4444', 81 | 600: '#dc2626', 82 | 700: '#b91c1c', 83 | 800: '#991b1b', 84 | 900: '#7f1d1d', 85 | }, 86 | orange: { 87 | 50: '#fff7ed', 88 | 100: '#ffedd5', 89 | 200: '#fed7aa', 90 | 300: '#fdba74', 91 | 400: '#fb923c', 92 | 500: '#f97316', 93 | 600: '#ea580c', 94 | 700: '#c2410c', 95 | 800: '#9a3412', 96 | 900: '#7c2d12', 97 | }, 98 | amber: { 99 | 50: '#fffbeb', 100 | 100: '#fef3c7', 101 | 200: '#fde68a', 102 | 300: '#fcd34d', 103 | 400: '#fbbf24', 104 | 500: '#f59e0b', 105 | 600: '#d97706', 106 | 700: '#b45309', 107 | 800: '#92400e', 108 | 900: '#78350f', 109 | }, 110 | yellow: { 111 | 50: '#fefce8', 112 | 100: '#fef9c3', 113 | 200: '#fef08a', 114 | 300: '#fde047', 115 | 400: '#facc15', 116 | 500: '#eab308', 117 | 600: '#ca8a04', 118 | 700: '#a16207', 119 | 800: '#854d0e', 120 | 900: '#713f12', 121 | }, 122 | lime: { 123 | 50: '#f7fee7', 124 | 100: '#ecfccb', 125 | 200: '#d9f99d', 126 | 300: '#bef264', 127 | 400: '#a3e635', 128 | 500: '#84cc16', 129 | 600: '#65a30d', 130 | 700: '#4d7c0f', 131 | 800: '#3f6212', 132 | 900: '#365314', 133 | }, 134 | green: { 135 | 50: '#f0fdf4', 136 | 100: '#dcfce7', 137 | 200: '#bbf7d0', 138 | 300: '#86efac', 139 | 400: '#4ade80', 140 | 500: '#22c55e', 141 | 600: '#16a34a', 142 | 700: '#15803d', 143 | 800: '#166534', 144 | 900: '#14532d', 145 | }, 146 | emerald: { 147 | 50: '#ecfdf5', 148 | 100: '#d1fae5', 149 | 200: '#a7f3d0', 150 | 300: '#6ee7b7', 151 | 400: '#34d399', 152 | 500: '#10b981', 153 | 600: '#059669', 154 | 700: '#047857', 155 | 800: '#065f46', 156 | 900: '#064e3b', 157 | }, 158 | teal: { 159 | 50: '#f0fdfa', 160 | 100: '#ccfbf1', 161 | 200: '#99f6e4', 162 | 300: '#5eead4', 163 | 400: '#2dd4bf', 164 | 500: '#14b8a6', 165 | 600: '#0d9488', 166 | 700: '#0f766e', 167 | 800: '#115e59', 168 | 900: '#134e4a', 169 | }, 170 | cyan: { 171 | 50: '#ecfeff', 172 | 100: '#cffafe', 173 | 200: '#a5f3fc', 174 | 300: '#67e8f9', 175 | 400: '#22d3ee', 176 | 500: '#06b6d4', 177 | 600: '#0891b2', 178 | 700: '#0e7490', 179 | 800: '#155e75', 180 | 900: '#164e63', 181 | }, 182 | sky: { 183 | 50: '#f0f9ff', 184 | 100: '#e0f2fe', 185 | 200: '#bae6fd', 186 | 300: '#7dd3fc', 187 | 400: '#38bdf8', 188 | 500: '#0ea5e9', 189 | 600: '#0284c7', 190 | 700: '#0369a1', 191 | 800: '#075985', 192 | 900: '#0c4a6e', 193 | }, 194 | blue: { 195 | 50: '#eff6ff', 196 | 100: '#dbeafe', 197 | 200: '#bfdbfe', 198 | 300: '#93c5fd', 199 | 400: '#60a5fa', 200 | 500: '#3b82f6', 201 | 600: '#2563eb', 202 | 700: '#1d4ed8', 203 | 800: '#1e40af', 204 | 900: '#1e3a8a', 205 | }, 206 | indigo: { 207 | 50: '#eef2ff', 208 | 100: '#e0e7ff', 209 | 200: '#c7d2fe', 210 | 300: '#a5b4fc', 211 | 400: '#818cf8', 212 | 500: '#6366f1', 213 | 600: '#4f46e5', 214 | 700: '#4338ca', 215 | 800: '#3730a3', 216 | 900: '#312e81', 217 | }, 218 | violet: { 219 | 50: '#f5f3ff', 220 | 100: '#ede9fe', 221 | 200: '#ddd6fe', 222 | 300: '#c4b5fd', 223 | 400: '#a78bfa', 224 | 500: '#8b5cf6', 225 | 600: '#7c3aed', 226 | 700: '#6d28d9', 227 | 800: '#5b21b6', 228 | 900: '#4c1d95', 229 | }, 230 | purple: { 231 | 50: '#faf5ff', 232 | 100: '#f3e8ff', 233 | 200: '#e9d5ff', 234 | 300: '#d8b4fe', 235 | 400: '#c084fc', 236 | 500: '#a855f7', 237 | 600: '#9333ea', 238 | 700: '#7e22ce', 239 | 800: '#6b21a8', 240 | 900: '#581c87', 241 | }, 242 | fuchsia: { 243 | 50: '#fdf4ff', 244 | 100: '#fae8ff', 245 | 200: '#f5d0fe', 246 | 300: '#f0abfc', 247 | 400: '#e879f9', 248 | 500: '#d946ef', 249 | 600: '#c026d3', 250 | 700: '#a21caf', 251 | 800: '#86198f', 252 | 900: '#701a75', 253 | }, 254 | pink: { 255 | 50: '#fdf2f8', 256 | 100: '#fce7f3', 257 | 200: '#fbcfe8', 258 | 300: '#f9a8d4', 259 | 400: '#f472b6', 260 | 500: '#ec4899', 261 | 600: '#db2777', 262 | 700: '#be185d', 263 | 800: '#9d174d', 264 | 900: '#831843', 265 | }, 266 | rose: { 267 | 50: '#fff1f2', 268 | 100: '#ffe4e6', 269 | 200: '#fecdd3', 270 | 300: '#fda4af', 271 | 400: '#fb7185', 272 | 500: '#f43f5e', 273 | 600: '#e11d48', 274 | 700: '#be123c', 275 | 800: '#9f1239', 276 | 900: '#881337', 277 | }, 278 | }; 279 | 280 | const tailwindColours = {}; 281 | 282 | for (const coloursKey in colours) { 283 | if (typeof colours[coloursKey] === 'string') { 284 | tailwindColours[coloursKey] = colours[coloursKey]; 285 | } else { 286 | for (const nestedKey in colours[coloursKey]) { 287 | tailwindColours[`${coloursKey}-${nestedKey}`] = 288 | colours[coloursKey][nestedKey]; 289 | } 290 | } 291 | } 292 | 293 | export class Inspector { 294 | public onCopy = (_color: string) => {}; 295 | 296 | private group: paper.Group; 297 | private cells: PixelCell[] = []; 298 | private raster: paper.Raster; 299 | 300 | private get targetCell() { 301 | return this.cells[(this.cells.length - 1) / 2]; 302 | } 303 | 304 | constructor(private project: PaperProject) { 305 | this.initUI(); 306 | this.trackMouse(); 307 | this.handleColorCopy(); 308 | } 309 | 310 | public loadImage(img: HTMLImageElement) { 311 | this.project.view.viewSize = new paper.Size(img.width, img.height); 312 | const rasterize = () => { 313 | const raster = new paper.Raster(img); 314 | raster.position = new paper.Point(img.width / 2, img.height / 2); 315 | raster.width = img.width; 316 | raster.height = img.height; 317 | raster.visible = false; 318 | this.raster = raster; 319 | 320 | // refresh 321 | this.moveTo(this.group.position); 322 | }; 323 | 324 | img.complete ? rasterize() : img.addEventListener('load', rasterize); 325 | } 326 | 327 | /** 328 | * Update inspector's position. 329 | * 330 | * @remarks 331 | * Update cell colors in the meanwhile if having the rater image. 332 | */ 333 | private moveTo(point: paper.Point) { 334 | this.group.position = point; 335 | if (this.raster) { 336 | this.cells.forEach((cell) => { 337 | cell.setColor(this.raster.getPixel(cell.position)); 338 | }); 339 | } 340 | } 341 | 342 | /** 343 | * Initialize inspector UI items, including the cursor and circular magnifier. 344 | */ 345 | private initUI() { 346 | const cursor = createCursor(); 347 | 348 | // make the inspector center representing the cursor center 349 | const offset = cursor.position.subtract((kInspectorSize - 1) / 2); 350 | for (let x = 0; x < kInspectorSize; x++) { 351 | for (let y = 0; y < kInspectorSize; y++) { 352 | this.cells.push( 353 | PixelCell.create({ 354 | pixelAt: new paper.Point(x, y), 355 | pivot: new paper.Point(x, y).add(offset), 356 | size: kCellSize, 357 | }), 358 | ); 359 | } 360 | } 361 | 362 | const magnifier = createCircleMask({ 363 | radius: (kInspectorSize * kCellSize) / 2, 364 | children: this.cells.map((c) => c.raw), 365 | }); 366 | this.targetCell.highlight(); 367 | 368 | this.group = new paper.Group([magnifier, cursor]); 369 | this.group.pivot = new paper.Point(0, 0); 370 | } 371 | 372 | /** 373 | * Keep inspector's position sync with mouse. 374 | */ 375 | private trackMouse() { 376 | this.project.view.on('mousemove', ({ point }) => { 377 | this.moveTo(point); 378 | }); 379 | 380 | document.body.addEventListener('mouseenter', ({ clientX, clientY }) => { 381 | this.moveTo(new paper.Point(clientX, clientY)); 382 | }); 383 | } 384 | 385 | /** 386 | * Deal with system copy and snackbar. 387 | */ 388 | private handleColorCopy() { 389 | this.project.view.on('click', () => { 390 | const color = this.targetCell.color; 391 | const getNearestTailwindColour = nearestColour.from(tailwindColours); 392 | const nearestTailwindColour = getNearestTailwindColour(color); 393 | copy(nearestTailwindColour['name']); 394 | this.onCopy(color); 395 | }); 396 | } 397 | } 398 | -------------------------------------------------------------------------------- /packages/colorins/src/lib/paper-project.ts: -------------------------------------------------------------------------------- 1 | import paper from 'paper'; 2 | 3 | export class PaperProject extends paper.Project {} 4 | 5 | export const paperProjectFactory = ( 6 | canvas: HTMLCanvasElement, 7 | ): PaperProject => { 8 | const project = new paper.Project(canvas); 9 | return project; 10 | }; 11 | -------------------------------------------------------------------------------- /packages/colorins/src/lib/pixel-cell.ts: -------------------------------------------------------------------------------- 1 | import paper from 'paper'; 2 | 3 | const kStrokeColor = new paper.Color('#646464'); 4 | const kHighlightStrokeColor = new paper.Color('#ff2020'); 5 | const kHighlightStrokeWidth = 3; 6 | 7 | export interface PixelCellInit { 8 | pixelAt: paper.Point; 9 | pivot: paper.Point; 10 | size: number; 11 | } 12 | 13 | /** 14 | * A class representing a pixel on a paper.Raster. 15 | * 16 | * @remarks 17 | * The cell rectangle is located wthin a coordinate having one unit equalts to `size`. 18 | */ 19 | export class PixelCell { 20 | private rect: paper.Path.Rectangle; 21 | 22 | public static create(init: PixelCellInit) { 23 | const cell = new PixelCell(init); 24 | return cell; 25 | } 26 | 27 | constructor({ pixelAt, pivot, size }: PixelCellInit) { 28 | this.rect = new paper.Path.Rectangle({ 29 | point: pixelAt.multiply(size), 30 | size: [size, size], 31 | strokeColor: kStrokeColor, 32 | }); 33 | this.rect.pivot = pivot; 34 | } 35 | 36 | public get raw(): paper.Item { 37 | return this.rect; 38 | } 39 | 40 | public get position() { 41 | return this.rect.position; 42 | } 43 | 44 | /** 45 | * @remarks 46 | * Color string in hex. 47 | */ 48 | public get color() { 49 | return this.rect.fillColor.toCSS(true); 50 | } 51 | 52 | public setColor(paperColor: paper.Color) { 53 | this.rect.fillColor = paperColor; 54 | } 55 | 56 | public highlight() { 57 | this.rect.bringToFront(); 58 | this.rect.strokeColor = kHighlightStrokeColor; 59 | this.rect.strokeWidth = kHighlightStrokeWidth; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/colorins/src/lib/primitive-factory.ts: -------------------------------------------------------------------------------- 1 | import paper from 'paper'; 2 | 3 | const kCursorRaduis = 14; 4 | const kCursorOffset = 18; 5 | const kCursorLineLength = 14; 6 | const kCursorLineWidth = 3; 7 | const kStrokeColor = new paper.Color('#777777'); 8 | const kStrokeWidth = 5; 9 | 10 | export function createCursor() { 11 | const cursor = new paper.Group([ 12 | new paper.Path.Circle({ 13 | center: new paper.Point(kCursorOffset, kCursorOffset), 14 | radius: kCursorRaduis, 15 | strokeWidth: kStrokeWidth * 1.2, 16 | strokeColor: kStrokeColor, 17 | }), 18 | new paper.Path.Line({ 19 | from: [kCursorOffset, kCursorOffset - kCursorRaduis], 20 | to: [kCursorOffset, kCursorOffset - kCursorRaduis - kCursorLineLength], 21 | strokeWidth: kCursorLineWidth, 22 | strokeColor: kStrokeColor, 23 | }), 24 | new paper.Path.Line({ 25 | from: [kCursorOffset, kCursorOffset + kCursorRaduis], 26 | to: [kCursorOffset, kCursorOffset + kCursorRaduis + kCursorLineLength], 27 | strokeWidth: kCursorLineWidth, 28 | strokeColor: kStrokeColor, 29 | }), 30 | new paper.Path.Line({ 31 | from: [kCursorOffset - kCursorRaduis, kCursorOffset], 32 | to: [kCursorOffset - kCursorRaduis - kCursorLineLength, kCursorOffset], 33 | strokeWidth: kCursorLineWidth, 34 | strokeColor: kStrokeColor, 35 | }), 36 | new paper.Path.Line({ 37 | from: [kCursorOffset + kCursorRaduis, kCursorOffset], 38 | to: [kCursorOffset + kCursorRaduis + kCursorLineLength, kCursorOffset], 39 | strokeWidth: kCursorLineWidth, 40 | strokeColor: kStrokeColor, 41 | }), 42 | ]); 43 | return cursor; 44 | } 45 | 46 | export function createCircleMask({ radius, children }) { 47 | const circleClip = new paper.Shape.Circle({ 48 | center: [radius, radius], 49 | radius: radius, 50 | }); 51 | 52 | const circleBorder = new paper.Shape.Circle({ 53 | center: [radius, radius], 54 | radius, 55 | strokeColor: kStrokeColor, 56 | strokeWidth: kStrokeWidth, 57 | }); 58 | 59 | const mask = new paper.Group([circleClip, ...children, circleBorder]); 60 | mask.clipped = true; 61 | 62 | return mask; 63 | } 64 | -------------------------------------------------------------------------------- /packages/colorins/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Helper for copying text to system clipboard. 3 | */ 4 | export function copy(text: string) { 5 | const input = document.createElement('textarea'); 6 | input.innerHTML = text; 7 | document.body.appendChild(input); 8 | input.select(); 9 | const result = document.execCommand('copy'); 10 | document.body.removeChild(input); 11 | return result; 12 | } 13 | -------------------------------------------------------------------------------- /packages/colorins/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "moduleResolution": "node", 7 | "module": "es6", 8 | "declaration": true, 9 | "inlineSourceMap": true, 10 | "esModuleInterop": true, 11 | "noUnusedLocals": true, 12 | "noUnusedParameters": true, 13 | "noImplicitReturns": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "traceResolution": false, 16 | "listEmittedFiles": false, 17 | "listFiles": false, 18 | "pretty": true, 19 | "experimentalDecorators": true, 20 | "emitDecoratorMetadata": true, 21 | "lib": ["es2017", "dom"], 22 | "emitDeclarationOnly": true, 23 | "declarationDir": "dist", 24 | "skipLibCheck": true 25 | }, 26 | "include": ["src/**/*.ts"], 27 | "exclude": ["node_modules"], 28 | "compileOnSave": false 29 | } 30 | -------------------------------------------------------------------------------- /packages/colorins/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.10.3" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.3.tgz#324bcfd8d35cd3d47dae18cde63d752086435e9a" 8 | dependencies: 9 | "@babel/highlight" "^7.10.3" 10 | 11 | "@babel/helper-validator-identifier@^7.10.3": 12 | version "7.10.3" 13 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz#60d9847f98c4cea1b279e005fdb7c28be5412d15" 14 | 15 | "@babel/highlight@^7.10.3": 16 | version "7.10.3" 17 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.3.tgz#c633bb34adf07c5c13156692f5922c81ec53f28d" 18 | dependencies: 19 | "@babel/helper-validator-identifier" "^7.10.3" 20 | chalk "^2.0.0" 21 | js-tokens "^4.0.0" 22 | 23 | "@bitjson/npm-scripts-info@^1.0.0": 24 | version "1.0.0" 25 | resolved "https://registry.yarnpkg.com/@bitjson/npm-scripts-info/-/npm-scripts-info-1.0.0.tgz#732426788b8861618b10c5d054f497fb4dd9165e" 26 | dependencies: 27 | chalk "^2.3.0" 28 | meow "^4.0.0" 29 | unquote "^1.1.0" 30 | 31 | "@bitjson/typedoc@^0.15.0-0": 32 | version "0.15.0-0" 33 | resolved "https://registry.yarnpkg.com/@bitjson/typedoc/-/typedoc-0.15.0-0.tgz#73373b3ecbcdced658c17d2d9cb1273ece6c840b" 34 | dependencies: 35 | "@types/minimatch" "3.0.3" 36 | fs-extra "^7.0.1" 37 | handlebars "^4.1.2" 38 | highlight.js "^9.13.1" 39 | lodash "^4.17.11" 40 | marked "^0.6.2" 41 | minimatch "^3.0.0" 42 | progress "^2.0.3" 43 | shelljs "^0.8.3" 44 | typedoc-default-themes "^0.6.0-0" 45 | typescript "3.5.x" 46 | 47 | "@sindresorhus/df@^1.0.1": 48 | version "1.0.1" 49 | resolved "https://registry.yarnpkg.com/@sindresorhus/df/-/df-1.0.1.tgz#c69b66f52f6fcdd287c807df210305dbaf78500d" 50 | 51 | "@sindresorhus/df@^2.1.0": 52 | version "2.1.0" 53 | resolved "https://registry.yarnpkg.com/@sindresorhus/df/-/df-2.1.0.tgz#d208cf27e06f0bb476d14d7deccd7d726e9aa389" 54 | dependencies: 55 | execa "^0.2.2" 56 | 57 | "@sindresorhus/is@^0.14.0": 58 | version "0.14.0" 59 | resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" 60 | 61 | "@stroncium/procfs@^1.0.0": 62 | version "1.2.1" 63 | resolved "https://registry.yarnpkg.com/@stroncium/procfs/-/procfs-1.2.1.tgz#6b9be6fd20fb0a4c20e99a8695e083c699bb2b45" 64 | 65 | "@szmarczak/http-timer@^1.1.2": 66 | version "1.1.2" 67 | resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" 68 | dependencies: 69 | defer-to-connect "^1.0.1" 70 | 71 | "@types/color-name@^1.1.1": 72 | version "1.1.1" 73 | resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" 74 | 75 | "@types/minimatch@3.0.3": 76 | version "3.0.3" 77 | resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" 78 | 79 | "@types/minimist@^1.2.0": 80 | version "1.2.0" 81 | resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" 82 | 83 | "@types/normalize-package-data@^2.4.0": 84 | version "2.4.0" 85 | resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" 86 | 87 | JSONStream@^1.0.4: 88 | version "1.3.5" 89 | resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" 90 | dependencies: 91 | jsonparse "^1.2.0" 92 | through ">=2.2.7 <3" 93 | 94 | add-stream@^1.0.0: 95 | version "1.0.0" 96 | resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" 97 | 98 | aggregate-error@^3.0.0: 99 | version "3.0.1" 100 | resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" 101 | dependencies: 102 | clean-stack "^2.0.0" 103 | indent-string "^4.0.0" 104 | 105 | ansi-align@^3.0.0: 106 | version "3.0.0" 107 | resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb" 108 | dependencies: 109 | string-width "^3.0.0" 110 | 111 | ansi-regex@^3.0.0: 112 | version "3.0.0" 113 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 114 | 115 | ansi-regex@^4.1.0: 116 | version "4.1.0" 117 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" 118 | 119 | ansi-regex@^5.0.0: 120 | version "5.0.0" 121 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" 122 | 123 | ansi-styles@^3.2.1: 124 | version "3.2.1" 125 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 126 | dependencies: 127 | color-convert "^1.9.0" 128 | 129 | ansi-styles@^4.0.0: 130 | version "4.2.1" 131 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" 132 | dependencies: 133 | "@types/color-name" "^1.1.1" 134 | color-convert "^2.0.1" 135 | 136 | array-find-index@^1.0.1: 137 | version "1.0.2" 138 | resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" 139 | 140 | array-ify@^1.0.0: 141 | version "1.0.0" 142 | resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" 143 | 144 | array-union@^1.0.1: 145 | version "1.0.2" 146 | resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 147 | dependencies: 148 | array-uniq "^1.0.1" 149 | 150 | array-uniq@^1.0.1: 151 | version "1.0.3" 152 | resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 153 | 154 | arrify@^1.0.1: 155 | version "1.0.1" 156 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 157 | 158 | arrify@^2.0.1: 159 | version "2.0.1" 160 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" 161 | 162 | backbone@^1.4.0: 163 | version "1.4.0" 164 | resolved "https://registry.yarnpkg.com/backbone/-/backbone-1.4.0.tgz#54db4de9df7c3811c3f032f34749a4cd27f3bd12" 165 | dependencies: 166 | underscore ">=1.8.3" 167 | 168 | balanced-match@^1.0.0: 169 | version "1.0.0" 170 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 171 | 172 | boxen@^3.0.0: 173 | version "3.2.0" 174 | resolved "https://registry.yarnpkg.com/boxen/-/boxen-3.2.0.tgz#fbdff0de93636ab4450886b6ff45b92d098f45eb" 175 | dependencies: 176 | ansi-align "^3.0.0" 177 | camelcase "^5.3.1" 178 | chalk "^2.4.2" 179 | cli-boxes "^2.2.0" 180 | string-width "^3.0.0" 181 | term-size "^1.2.0" 182 | type-fest "^0.3.0" 183 | widest-line "^2.0.0" 184 | 185 | brace-expansion@^1.1.7: 186 | version "1.1.11" 187 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 188 | dependencies: 189 | balanced-match "^1.0.0" 190 | concat-map "0.0.1" 191 | 192 | buffer-from@^1.0.0: 193 | version "1.1.1" 194 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 195 | 196 | cacheable-request@^6.0.0: 197 | version "6.1.0" 198 | resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" 199 | dependencies: 200 | clone-response "^1.0.2" 201 | get-stream "^5.1.0" 202 | http-cache-semantics "^4.0.0" 203 | keyv "^3.0.0" 204 | lowercase-keys "^2.0.0" 205 | normalize-url "^4.1.0" 206 | responselike "^1.0.2" 207 | 208 | camelcase-keys@^2.0.0: 209 | version "2.1.0" 210 | resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" 211 | dependencies: 212 | camelcase "^2.0.0" 213 | map-obj "^1.0.0" 214 | 215 | camelcase-keys@^4.0.0: 216 | version "4.2.0" 217 | resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" 218 | dependencies: 219 | camelcase "^4.1.0" 220 | map-obj "^2.0.0" 221 | quick-lru "^1.0.0" 222 | 223 | camelcase-keys@^6.2.2: 224 | version "6.2.2" 225 | resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" 226 | dependencies: 227 | camelcase "^5.3.1" 228 | map-obj "^4.0.0" 229 | quick-lru "^4.0.1" 230 | 231 | camelcase@^2.0.0: 232 | version "2.1.1" 233 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" 234 | 235 | camelcase@^4.1.0: 236 | version "4.1.0" 237 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" 238 | 239 | camelcase@^5.0.0, camelcase@^5.3.1: 240 | version "5.3.1" 241 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" 242 | 243 | camelcase@^6.0.0: 244 | version "6.0.0" 245 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" 246 | 247 | chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2: 248 | version "2.4.2" 249 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 250 | dependencies: 251 | ansi-styles "^3.2.1" 252 | escape-string-regexp "^1.0.5" 253 | supports-color "^5.3.0" 254 | 255 | ci-info@^2.0.0: 256 | version "2.0.0" 257 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" 258 | 259 | clean-stack@^2.0.0: 260 | version "2.2.0" 261 | resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" 262 | 263 | cli-boxes@^2.2.0: 264 | version "2.2.0" 265 | resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d" 266 | 267 | cliui@^6.0.0: 268 | version "6.0.0" 269 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" 270 | dependencies: 271 | string-width "^4.2.0" 272 | strip-ansi "^6.0.0" 273 | wrap-ansi "^6.2.0" 274 | 275 | clone-response@^1.0.2: 276 | version "1.0.2" 277 | resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" 278 | dependencies: 279 | mimic-response "^1.0.0" 280 | 281 | color-convert@^1.9.0: 282 | version "1.9.3" 283 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 284 | dependencies: 285 | color-name "1.1.3" 286 | 287 | color-convert@^2.0.1: 288 | version "2.0.1" 289 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 290 | dependencies: 291 | color-name "~1.1.4" 292 | 293 | color-name@1.1.3: 294 | version "1.1.3" 295 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 296 | 297 | color-name@~1.1.4: 298 | version "1.1.4" 299 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 300 | 301 | compare-func@^1.3.1: 302 | version "1.3.4" 303 | resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.4.tgz#6b07c4c5e8341119baf44578085bda0f4a823516" 304 | dependencies: 305 | array-ify "^1.0.0" 306 | dot-prop "^3.0.0" 307 | 308 | concat-map@0.0.1: 309 | version "0.0.1" 310 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 311 | 312 | concat-stream@^2.0.0: 313 | version "2.0.0" 314 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" 315 | dependencies: 316 | buffer-from "^1.0.0" 317 | inherits "^2.0.3" 318 | readable-stream "^3.0.2" 319 | typedarray "^0.0.6" 320 | 321 | configstore@^4.0.0: 322 | version "4.0.0" 323 | resolved "https://registry.yarnpkg.com/configstore/-/configstore-4.0.0.tgz#5933311e95d3687efb592c528b922d9262d227e7" 324 | dependencies: 325 | dot-prop "^4.1.0" 326 | graceful-fs "^4.1.2" 327 | make-dir "^1.0.0" 328 | unique-string "^1.0.0" 329 | write-file-atomic "^2.0.0" 330 | xdg-basedir "^3.0.0" 331 | 332 | conventional-changelog-angular@^5.0.10: 333 | version "5.0.10" 334 | resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.10.tgz#5cf7b00dd315b6a6a558223c80d5ef24ddb34205" 335 | dependencies: 336 | compare-func "^1.3.1" 337 | q "^1.5.1" 338 | 339 | conventional-changelog-atom@^2.0.7: 340 | version "2.0.7" 341 | resolved "https://registry.yarnpkg.com/conventional-changelog-atom/-/conventional-changelog-atom-2.0.7.tgz#221575253a04f77a2fd273eb2bf29a138f710abf" 342 | dependencies: 343 | q "^1.5.1" 344 | 345 | conventional-changelog-codemirror@^2.0.7: 346 | version "2.0.7" 347 | resolved "https://registry.yarnpkg.com/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.7.tgz#d6b6a8ce2707710c5a036e305037547fb9e15bfb" 348 | dependencies: 349 | q "^1.5.1" 350 | 351 | conventional-changelog-config-spec@2.1.0: 352 | version "2.1.0" 353 | resolved "https://registry.yarnpkg.com/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz#874a635287ef8b581fd8558532bf655d4fb59f2d" 354 | 355 | conventional-changelog-conventionalcommits@4.3.0, conventional-changelog-conventionalcommits@^4.3.0: 356 | version "4.3.0" 357 | resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.3.0.tgz#c4205a659f7ca9d7881f29ee78a4e7d6aeb8b3c2" 358 | dependencies: 359 | compare-func "^1.3.1" 360 | lodash "^4.17.15" 361 | q "^1.5.1" 362 | 363 | conventional-changelog-core@^4.1.7: 364 | version "4.1.7" 365 | resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-4.1.7.tgz#6b5cdadda4430895cc4a75a73dd8b36e322ab346" 366 | dependencies: 367 | add-stream "^1.0.0" 368 | conventional-changelog-writer "^4.0.16" 369 | conventional-commits-parser "^3.1.0" 370 | dateformat "^3.0.0" 371 | get-pkg-repo "^1.0.0" 372 | git-raw-commits "2.0.0" 373 | git-remote-origin-url "^2.0.0" 374 | git-semver-tags "^4.0.0" 375 | lodash "^4.17.15" 376 | normalize-package-data "^2.3.5" 377 | q "^1.5.1" 378 | read-pkg "^3.0.0" 379 | read-pkg-up "^3.0.0" 380 | shelljs "^0.8.3" 381 | through2 "^3.0.0" 382 | 383 | conventional-changelog-ember@^2.0.8: 384 | version "2.0.8" 385 | resolved "https://registry.yarnpkg.com/conventional-changelog-ember/-/conventional-changelog-ember-2.0.8.tgz#f0f04eb7ff3c885af97db100865ab95dcfa9917f" 386 | dependencies: 387 | q "^1.5.1" 388 | 389 | conventional-changelog-eslint@^3.0.8: 390 | version "3.0.8" 391 | resolved "https://registry.yarnpkg.com/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.8.tgz#f8b952b7ed7253ea0ac0b30720bb381f4921b46c" 392 | dependencies: 393 | q "^1.5.1" 394 | 395 | conventional-changelog-express@^2.0.5: 396 | version "2.0.5" 397 | resolved "https://registry.yarnpkg.com/conventional-changelog-express/-/conventional-changelog-express-2.0.5.tgz#6e93705acdad374516ca125990012a48e710f8de" 398 | dependencies: 399 | q "^1.5.1" 400 | 401 | conventional-changelog-jquery@^3.0.10: 402 | version "3.0.10" 403 | resolved "https://registry.yarnpkg.com/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.10.tgz#fe8eb6aff322aa980af5eb68497622a5f6257ce7" 404 | dependencies: 405 | q "^1.5.1" 406 | 407 | conventional-changelog-jshint@^2.0.7: 408 | version "2.0.7" 409 | resolved "https://registry.yarnpkg.com/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.7.tgz#955a69266951cd31e8afeb3f1c55e0517fdca943" 410 | dependencies: 411 | compare-func "^1.3.1" 412 | q "^1.5.1" 413 | 414 | conventional-changelog-preset-loader@^2.3.4: 415 | version "2.3.4" 416 | resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c" 417 | 418 | conventional-changelog-writer@^4.0.16: 419 | version "4.0.16" 420 | resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.16.tgz#ca10f2691a8ea6d3c2eb74bd35bcf40aa052dda5" 421 | dependencies: 422 | compare-func "^1.3.1" 423 | conventional-commits-filter "^2.0.6" 424 | dateformat "^3.0.0" 425 | handlebars "^4.7.6" 426 | json-stringify-safe "^5.0.1" 427 | lodash "^4.17.15" 428 | meow "^7.0.0" 429 | semver "^6.0.0" 430 | split "^1.0.0" 431 | through2 "^3.0.0" 432 | 433 | conventional-changelog@3.1.21: 434 | version "3.1.21" 435 | resolved "https://registry.yarnpkg.com/conventional-changelog/-/conventional-changelog-3.1.21.tgz#4a774e6bf503acfd7e4685bb750da8c0eccf1e0d" 436 | dependencies: 437 | conventional-changelog-angular "^5.0.10" 438 | conventional-changelog-atom "^2.0.7" 439 | conventional-changelog-codemirror "^2.0.7" 440 | conventional-changelog-conventionalcommits "^4.3.0" 441 | conventional-changelog-core "^4.1.7" 442 | conventional-changelog-ember "^2.0.8" 443 | conventional-changelog-eslint "^3.0.8" 444 | conventional-changelog-express "^2.0.5" 445 | conventional-changelog-jquery "^3.0.10" 446 | conventional-changelog-jshint "^2.0.7" 447 | conventional-changelog-preset-loader "^2.3.4" 448 | 449 | conventional-commits-filter@^2.0.6: 450 | version "2.0.6" 451 | resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.6.tgz#0935e1240c5ca7698329affee1b6a46d33324c4c" 452 | dependencies: 453 | lodash.ismatch "^4.4.0" 454 | modify-values "^1.0.0" 455 | 456 | conventional-commits-parser@^3.1.0: 457 | version "3.1.0" 458 | resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.1.0.tgz#10140673d5e7ef5572633791456c5d03b69e8be4" 459 | dependencies: 460 | JSONStream "^1.0.4" 461 | is-text-path "^1.0.1" 462 | lodash "^4.17.15" 463 | meow "^7.0.0" 464 | split2 "^2.0.0" 465 | through2 "^3.0.0" 466 | trim-off-newlines "^1.0.0" 467 | 468 | conventional-recommended-bump@6.0.9: 469 | version "6.0.9" 470 | resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-6.0.9.tgz#49ee74f52fbafcc63e89e2297d020279fea318f0" 471 | dependencies: 472 | concat-stream "^2.0.0" 473 | conventional-changelog-preset-loader "^2.3.4" 474 | conventional-commits-filter "^2.0.6" 475 | conventional-commits-parser "^3.1.0" 476 | git-raw-commits "2.0.0" 477 | git-semver-tags "^4.0.0" 478 | meow "^7.0.0" 479 | q "^1.5.1" 480 | 481 | core-util-is@~1.0.0: 482 | version "1.0.2" 483 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 484 | 485 | cp-file@^6.1.0: 486 | version "6.2.0" 487 | resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-6.2.0.tgz#40d5ea4a1def2a9acdd07ba5c0b0246ef73dc10d" 488 | dependencies: 489 | graceful-fs "^4.1.2" 490 | make-dir "^2.0.0" 491 | nested-error-stacks "^2.0.0" 492 | pify "^4.0.1" 493 | safe-buffer "^5.0.1" 494 | 495 | cross-spawn-async@^2.1.1: 496 | version "2.2.5" 497 | resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" 498 | dependencies: 499 | lru-cache "^4.0.0" 500 | which "^1.2.8" 501 | 502 | cross-spawn@^5.0.1: 503 | version "5.1.0" 504 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" 505 | dependencies: 506 | lru-cache "^4.0.1" 507 | shebang-command "^1.2.0" 508 | which "^1.2.9" 509 | 510 | crypto-random-string@^1.0.0: 511 | version "1.0.0" 512 | resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" 513 | 514 | currently-unhandled@^0.4.1: 515 | version "0.4.1" 516 | resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" 517 | dependencies: 518 | array-find-index "^1.0.1" 519 | 520 | dargs@^4.0.1: 521 | version "4.1.0" 522 | resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" 523 | dependencies: 524 | number-is-nan "^1.0.0" 525 | 526 | dateformat@^3.0.0: 527 | version "3.0.3" 528 | resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" 529 | 530 | decamelize-keys@^1.0.0, decamelize-keys@^1.1.0: 531 | version "1.1.0" 532 | resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" 533 | dependencies: 534 | decamelize "^1.1.0" 535 | map-obj "^1.0.0" 536 | 537 | decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: 538 | version "1.2.0" 539 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 540 | 541 | decompress-response@^3.3.0: 542 | version "3.3.0" 543 | resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" 544 | dependencies: 545 | mimic-response "^1.0.0" 546 | 547 | deep-extend@^0.6.0: 548 | version "0.6.0" 549 | resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" 550 | 551 | defer-to-connect@^1.0.1: 552 | version "1.1.3" 553 | resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" 554 | 555 | detect-indent@^6.0.0: 556 | version "6.0.0" 557 | resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" 558 | 559 | detect-newline@^3.1.0: 560 | version "3.1.0" 561 | resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" 562 | 563 | dir-glob@^2.0.0: 564 | version "2.2.2" 565 | resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" 566 | dependencies: 567 | path-type "^3.0.0" 568 | 569 | dot-prop@^3.0.0: 570 | version "3.0.0" 571 | resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" 572 | dependencies: 573 | is-obj "^1.0.0" 574 | 575 | dot-prop@^4.1.0: 576 | version "4.2.0" 577 | resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" 578 | dependencies: 579 | is-obj "^1.0.0" 580 | 581 | dotgitignore@^2.1.0: 582 | version "2.1.0" 583 | resolved "https://registry.yarnpkg.com/dotgitignore/-/dotgitignore-2.1.0.tgz#a4b15a4e4ef3cf383598aaf1dfa4a04bcc089b7b" 584 | dependencies: 585 | find-up "^3.0.0" 586 | minimatch "^3.0.4" 587 | 588 | duplexer3@^0.1.4: 589 | version "0.1.4" 590 | resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" 591 | 592 | emoji-regex@^7.0.1: 593 | version "7.0.3" 594 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" 595 | 596 | emoji-regex@^8.0.0: 597 | version "8.0.0" 598 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" 599 | 600 | end-of-stream@^1.1.0: 601 | version "1.4.4" 602 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 603 | dependencies: 604 | once "^1.4.0" 605 | 606 | error-ex@^1.2.0, error-ex@^1.3.1: 607 | version "1.3.2" 608 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 609 | dependencies: 610 | is-arrayish "^0.2.1" 611 | 612 | escape-string-regexp@^1.0.5: 613 | version "1.0.5" 614 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 615 | 616 | execa@^0.2.2: 617 | version "0.2.2" 618 | resolved "https://registry.yarnpkg.com/execa/-/execa-0.2.2.tgz#e2ead472c2c31aad6f73f1ac956eef45e12320cb" 619 | dependencies: 620 | cross-spawn-async "^2.1.1" 621 | npm-run-path "^1.0.0" 622 | object-assign "^4.0.1" 623 | path-key "^1.0.0" 624 | strip-eof "^1.0.0" 625 | 626 | execa@^0.7.0: 627 | version "0.7.0" 628 | resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" 629 | dependencies: 630 | cross-spawn "^5.0.1" 631 | get-stream "^3.0.0" 632 | is-stream "^1.1.0" 633 | npm-run-path "^2.0.0" 634 | p-finally "^1.0.0" 635 | signal-exit "^3.0.0" 636 | strip-eof "^1.0.0" 637 | 638 | figures@^3.1.0: 639 | version "3.2.0" 640 | resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" 641 | dependencies: 642 | escape-string-regexp "^1.0.5" 643 | 644 | file-type@^11.0.0: 645 | version "11.1.0" 646 | resolved "https://registry.yarnpkg.com/file-type/-/file-type-11.1.0.tgz#93780f3fed98b599755d846b99a1617a2ad063b8" 647 | 648 | find-up@^1.0.0: 649 | version "1.1.2" 650 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" 651 | dependencies: 652 | path-exists "^2.0.0" 653 | pinkie-promise "^2.0.0" 654 | 655 | find-up@^2.0.0: 656 | version "2.1.0" 657 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" 658 | dependencies: 659 | locate-path "^2.0.0" 660 | 661 | find-up@^3.0.0: 662 | version "3.0.0" 663 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" 664 | dependencies: 665 | locate-path "^3.0.0" 666 | 667 | find-up@^4.1.0: 668 | version "4.1.0" 669 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 670 | dependencies: 671 | locate-path "^5.0.0" 672 | path-exists "^4.0.0" 673 | 674 | fs-access@^1.0.1: 675 | version "1.0.1" 676 | resolved "https://registry.yarnpkg.com/fs-access/-/fs-access-1.0.1.tgz#d6a87f262271cefebec30c553407fb995da8777a" 677 | dependencies: 678 | null-check "^1.0.0" 679 | 680 | fs-extra@^7.0.1: 681 | version "7.0.1" 682 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" 683 | dependencies: 684 | graceful-fs "^4.1.2" 685 | jsonfile "^4.0.0" 686 | universalify "^0.1.0" 687 | 688 | fs.realpath@^1.0.0: 689 | version "1.0.0" 690 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 691 | 692 | get-caller-file@^2.0.1: 693 | version "2.0.5" 694 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" 695 | 696 | get-pkg-repo@^1.0.0: 697 | version "1.4.0" 698 | resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" 699 | dependencies: 700 | hosted-git-info "^2.1.4" 701 | meow "^3.3.0" 702 | normalize-package-data "^2.3.0" 703 | parse-github-repo-url "^1.3.0" 704 | through2 "^2.0.0" 705 | 706 | get-stdin@^4.0.1: 707 | version "4.0.1" 708 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" 709 | 710 | get-stdin@^7.0.0: 711 | version "7.0.0" 712 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" 713 | 714 | get-stream@^3.0.0: 715 | version "3.0.0" 716 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 717 | 718 | get-stream@^4.1.0: 719 | version "4.1.0" 720 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" 721 | dependencies: 722 | pump "^3.0.0" 723 | 724 | get-stream@^5.1.0: 725 | version "5.1.0" 726 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" 727 | dependencies: 728 | pump "^3.0.0" 729 | 730 | git-raw-commits@2.0.0: 731 | version "2.0.0" 732 | resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5" 733 | dependencies: 734 | dargs "^4.0.1" 735 | lodash.template "^4.0.2" 736 | meow "^4.0.0" 737 | split2 "^2.0.0" 738 | through2 "^2.0.0" 739 | 740 | git-remote-origin-url@^2.0.0: 741 | version "2.0.0" 742 | resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" 743 | dependencies: 744 | gitconfiglocal "^1.0.0" 745 | pify "^2.3.0" 746 | 747 | git-semver-tags@^4.0.0: 748 | version "4.0.0" 749 | resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-4.0.0.tgz#a9dd58a0dd3561a4a9898b7e9731cf441c98fc38" 750 | dependencies: 751 | meow "^7.0.0" 752 | semver "^6.0.0" 753 | 754 | gitconfiglocal@^1.0.0: 755 | version "1.0.0" 756 | resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" 757 | dependencies: 758 | ini "^1.3.2" 759 | 760 | glob@^7.0.0, glob@^7.1.2: 761 | version "7.1.6" 762 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 763 | dependencies: 764 | fs.realpath "^1.0.0" 765 | inflight "^1.0.4" 766 | inherits "2" 767 | minimatch "^3.0.4" 768 | once "^1.3.0" 769 | path-is-absolute "^1.0.0" 770 | 771 | global-dirs@^0.1.0: 772 | version "0.1.1" 773 | resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" 774 | dependencies: 775 | ini "^1.3.4" 776 | 777 | globby@^7.1.1: 778 | version "7.1.1" 779 | resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" 780 | dependencies: 781 | array-union "^1.0.1" 782 | dir-glob "^2.0.0" 783 | glob "^7.1.2" 784 | ignore "^3.3.5" 785 | pify "^3.0.0" 786 | slash "^1.0.0" 787 | 788 | got@^9.6.0: 789 | version "9.6.0" 790 | resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" 791 | dependencies: 792 | "@sindresorhus/is" "^0.14.0" 793 | "@szmarczak/http-timer" "^1.1.2" 794 | cacheable-request "^6.0.0" 795 | decompress-response "^3.3.0" 796 | duplexer3 "^0.1.4" 797 | get-stream "^4.1.0" 798 | lowercase-keys "^1.0.1" 799 | mimic-response "^1.0.1" 800 | p-cancelable "^1.0.0" 801 | to-readable-stream "^1.0.0" 802 | url-parse-lax "^3.0.0" 803 | 804 | graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6: 805 | version "4.2.4" 806 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" 807 | 808 | handlebars@^4.1.2, handlebars@^4.7.6: 809 | version "4.7.6" 810 | resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" 811 | dependencies: 812 | minimist "^1.2.5" 813 | neo-async "^2.6.0" 814 | source-map "^0.6.1" 815 | wordwrap "^1.0.0" 816 | optionalDependencies: 817 | uglify-js "^3.1.4" 818 | 819 | hard-rejection@^2.1.0: 820 | version "2.1.0" 821 | resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" 822 | 823 | has-flag@^3.0.0: 824 | version "3.0.0" 825 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 826 | 827 | has-yarn@^2.1.0: 828 | version "2.1.0" 829 | resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" 830 | 831 | highlight.js@^9.13.1: 832 | version "9.18.1" 833 | resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.1.tgz#ed21aa001fe6252bb10a3d76d47573c6539fe13c" 834 | 835 | hosted-git-info@^2.1.4: 836 | version "2.8.8" 837 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" 838 | 839 | http-cache-semantics@^4.0.0: 840 | version "4.1.0" 841 | resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" 842 | 843 | ignore@^3.3.5: 844 | version "3.3.10" 845 | resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" 846 | 847 | import-lazy@^2.1.0: 848 | version "2.1.0" 849 | resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" 850 | 851 | imurmurhash@^0.1.4: 852 | version "0.1.4" 853 | resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" 854 | 855 | indent-string@^2.1.0: 856 | version "2.1.0" 857 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" 858 | dependencies: 859 | repeating "^2.0.0" 860 | 861 | indent-string@^3.0.0: 862 | version "3.2.0" 863 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" 864 | 865 | indent-string@^4.0.0: 866 | version "4.0.0" 867 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" 868 | 869 | inflight@^1.0.4: 870 | version "1.0.6" 871 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 872 | dependencies: 873 | once "^1.3.0" 874 | wrappy "1" 875 | 876 | inherits@2, inherits@^2.0.3, inherits@~2.0.3: 877 | version "2.0.4" 878 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 879 | 880 | ini@^1.3.2, ini@^1.3.4, ini@~1.3.0: 881 | version "1.3.5" 882 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" 883 | 884 | interpret@^1.0.0: 885 | version "1.4.0" 886 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" 887 | 888 | is-arrayish@^0.2.1: 889 | version "0.2.1" 890 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 891 | 892 | is-ci@^2.0.0: 893 | version "2.0.0" 894 | resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" 895 | dependencies: 896 | ci-info "^2.0.0" 897 | 898 | is-finite@^1.0.0: 899 | version "1.1.0" 900 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" 901 | 902 | is-fullwidth-code-point@^2.0.0: 903 | version "2.0.0" 904 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 905 | 906 | is-fullwidth-code-point@^3.0.0: 907 | version "3.0.0" 908 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" 909 | 910 | is-installed-globally@^0.1.0: 911 | version "0.1.0" 912 | resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" 913 | dependencies: 914 | global-dirs "^0.1.0" 915 | is-path-inside "^1.0.0" 916 | 917 | is-npm@^3.0.0: 918 | version "3.0.0" 919 | resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-3.0.0.tgz#ec9147bfb629c43f494cf67936a961edec7e8053" 920 | 921 | is-obj@^1.0.0: 922 | version "1.0.1" 923 | resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" 924 | 925 | is-path-inside@^1.0.0: 926 | version "1.0.1" 927 | resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" 928 | dependencies: 929 | path-is-inside "^1.0.1" 930 | 931 | is-path-inside@^3.0.2: 932 | version "3.0.2" 933 | resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" 934 | 935 | is-plain-obj@^1.1.0: 936 | version "1.1.0" 937 | resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" 938 | 939 | is-stream@^1.1.0: 940 | version "1.1.0" 941 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 942 | 943 | is-stream@^2.0.0: 944 | version "2.0.0" 945 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" 946 | 947 | is-text-path@^1.0.1: 948 | version "1.0.1" 949 | resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" 950 | dependencies: 951 | text-extensions "^1.0.0" 952 | 953 | is-utf8@^0.2.0: 954 | version "0.2.1" 955 | resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" 956 | 957 | is-wsl@^1.1.0: 958 | version "1.1.0" 959 | resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" 960 | 961 | is-yarn-global@^0.3.0: 962 | version "0.3.0" 963 | resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" 964 | 965 | isarray@~1.0.0: 966 | version "1.0.0" 967 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 968 | 969 | isexe@^2.0.0: 970 | version "2.0.0" 971 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 972 | 973 | jquery@^3.4.1: 974 | version "3.5.1" 975 | resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5" 976 | 977 | js-tokens@^4.0.0: 978 | version "4.0.0" 979 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 980 | 981 | json-buffer@3.0.0: 982 | version "3.0.0" 983 | resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" 984 | 985 | json-parse-better-errors@^1.0.1: 986 | version "1.0.2" 987 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 988 | 989 | json-stringify-safe@^5.0.1: 990 | version "5.0.1" 991 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 992 | 993 | jsonfile@^4.0.0: 994 | version "4.0.0" 995 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" 996 | optionalDependencies: 997 | graceful-fs "^4.1.6" 998 | 999 | jsonparse@^1.2.0: 1000 | version "1.3.1" 1001 | resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" 1002 | 1003 | keyv@^3.0.0: 1004 | version "3.1.0" 1005 | resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" 1006 | dependencies: 1007 | json-buffer "3.0.0" 1008 | 1009 | kind-of@^6.0.3: 1010 | version "6.0.3" 1011 | resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" 1012 | 1013 | latest-version@^5.0.0: 1014 | version "5.1.0" 1015 | resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face" 1016 | dependencies: 1017 | package-json "^6.3.0" 1018 | 1019 | lines-and-columns@^1.1.6: 1020 | version "1.1.6" 1021 | resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" 1022 | 1023 | load-json-file@^1.0.0: 1024 | version "1.1.0" 1025 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" 1026 | dependencies: 1027 | graceful-fs "^4.1.2" 1028 | parse-json "^2.2.0" 1029 | pify "^2.0.0" 1030 | pinkie-promise "^2.0.0" 1031 | strip-bom "^2.0.0" 1032 | 1033 | load-json-file@^4.0.0: 1034 | version "4.0.0" 1035 | resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" 1036 | dependencies: 1037 | graceful-fs "^4.1.2" 1038 | parse-json "^4.0.0" 1039 | pify "^3.0.0" 1040 | strip-bom "^3.0.0" 1041 | 1042 | locate-path@^2.0.0: 1043 | version "2.0.0" 1044 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" 1045 | dependencies: 1046 | p-locate "^2.0.0" 1047 | path-exists "^3.0.0" 1048 | 1049 | locate-path@^3.0.0: 1050 | version "3.0.0" 1051 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" 1052 | dependencies: 1053 | p-locate "^3.0.0" 1054 | path-exists "^3.0.0" 1055 | 1056 | locate-path@^5.0.0: 1057 | version "5.0.0" 1058 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 1059 | dependencies: 1060 | p-locate "^4.1.0" 1061 | 1062 | lodash._reinterpolate@^3.0.0: 1063 | version "3.0.0" 1064 | resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" 1065 | 1066 | lodash.ismatch@^4.4.0: 1067 | version "4.4.0" 1068 | resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" 1069 | 1070 | lodash.template@^4.0.2: 1071 | version "4.5.0" 1072 | resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" 1073 | dependencies: 1074 | lodash._reinterpolate "^3.0.0" 1075 | lodash.templatesettings "^4.0.0" 1076 | 1077 | lodash.templatesettings@^4.0.0: 1078 | version "4.2.0" 1079 | resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" 1080 | dependencies: 1081 | lodash._reinterpolate "^3.0.0" 1082 | 1083 | lodash@^4.17.11, lodash@^4.17.15: 1084 | version "4.17.19" 1085 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" 1086 | 1087 | loud-rejection@^1.0.0: 1088 | version "1.6.0" 1089 | resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" 1090 | dependencies: 1091 | currently-unhandled "^0.4.1" 1092 | signal-exit "^3.0.0" 1093 | 1094 | lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: 1095 | version "1.0.1" 1096 | resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" 1097 | 1098 | lowercase-keys@^2.0.0: 1099 | version "2.0.0" 1100 | resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" 1101 | 1102 | lru-cache@^4.0.0, lru-cache@^4.0.1: 1103 | version "4.1.5" 1104 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" 1105 | dependencies: 1106 | pseudomap "^1.0.2" 1107 | yallist "^2.1.2" 1108 | 1109 | lunr@^2.3.8: 1110 | version "2.3.8" 1111 | resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.8.tgz#a8b89c31f30b5a044b97d2d28e2da191b6ba2072" 1112 | 1113 | make-dir@^1.0.0: 1114 | version "1.3.0" 1115 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" 1116 | dependencies: 1117 | pify "^3.0.0" 1118 | 1119 | make-dir@^2.0.0: 1120 | version "2.1.0" 1121 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" 1122 | dependencies: 1123 | pify "^4.0.1" 1124 | semver "^5.6.0" 1125 | 1126 | make-dir@^3.0.0: 1127 | version "3.1.0" 1128 | resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" 1129 | dependencies: 1130 | semver "^6.0.0" 1131 | 1132 | map-obj@^1.0.0, map-obj@^1.0.1: 1133 | version "1.0.1" 1134 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" 1135 | 1136 | map-obj@^2.0.0: 1137 | version "2.0.0" 1138 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" 1139 | 1140 | map-obj@^4.0.0: 1141 | version "4.1.0" 1142 | resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" 1143 | 1144 | marked@^0.6.2: 1145 | version "0.6.3" 1146 | resolved "https://registry.yarnpkg.com/marked/-/marked-0.6.3.tgz#79babad78af638ba4d522a9e715cdfdd2429e946" 1147 | 1148 | meow@^3.3.0, meow@^3.7.0: 1149 | version "3.7.0" 1150 | resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" 1151 | dependencies: 1152 | camelcase-keys "^2.0.0" 1153 | decamelize "^1.1.2" 1154 | loud-rejection "^1.0.0" 1155 | map-obj "^1.0.1" 1156 | minimist "^1.1.3" 1157 | normalize-package-data "^2.3.4" 1158 | object-assign "^4.0.1" 1159 | read-pkg-up "^1.0.1" 1160 | redent "^1.0.0" 1161 | trim-newlines "^1.0.0" 1162 | 1163 | meow@^4.0.0: 1164 | version "4.0.1" 1165 | resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.1.tgz#d48598f6f4b1472f35bf6317a95945ace347f975" 1166 | dependencies: 1167 | camelcase-keys "^4.0.0" 1168 | decamelize-keys "^1.0.0" 1169 | loud-rejection "^1.0.0" 1170 | minimist "^1.1.3" 1171 | minimist-options "^3.0.1" 1172 | normalize-package-data "^2.3.4" 1173 | read-pkg-up "^3.0.0" 1174 | redent "^2.0.0" 1175 | trim-newlines "^2.0.0" 1176 | 1177 | meow@^5.0.0: 1178 | version "5.0.0" 1179 | resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" 1180 | dependencies: 1181 | camelcase-keys "^4.0.0" 1182 | decamelize-keys "^1.0.0" 1183 | loud-rejection "^1.0.0" 1184 | minimist-options "^3.0.1" 1185 | normalize-package-data "^2.3.4" 1186 | read-pkg-up "^3.0.0" 1187 | redent "^2.0.0" 1188 | trim-newlines "^2.0.0" 1189 | yargs-parser "^10.0.0" 1190 | 1191 | meow@^7.0.0: 1192 | version "7.0.1" 1193 | resolved "https://registry.yarnpkg.com/meow/-/meow-7.0.1.tgz#1ed4a0a50b3844b451369c48362eb0515f04c1dc" 1194 | dependencies: 1195 | "@types/minimist" "^1.2.0" 1196 | arrify "^2.0.1" 1197 | camelcase "^6.0.0" 1198 | camelcase-keys "^6.2.2" 1199 | decamelize-keys "^1.1.0" 1200 | hard-rejection "^2.1.0" 1201 | minimist-options "^4.0.2" 1202 | normalize-package-data "^2.5.0" 1203 | read-pkg-up "^7.0.1" 1204 | redent "^3.0.0" 1205 | trim-newlines "^3.0.0" 1206 | type-fest "^0.13.1" 1207 | yargs-parser "^18.1.3" 1208 | 1209 | mimic-response@^1.0.0, mimic-response@^1.0.1: 1210 | version "1.0.1" 1211 | resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" 1212 | 1213 | min-indent@^1.0.0: 1214 | version "1.0.1" 1215 | resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" 1216 | 1217 | minimatch@^3.0.0, minimatch@^3.0.4: 1218 | version "3.0.4" 1219 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 1220 | dependencies: 1221 | brace-expansion "^1.1.7" 1222 | 1223 | minimist-options@^3.0.1: 1224 | version "3.0.2" 1225 | resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" 1226 | dependencies: 1227 | arrify "^1.0.1" 1228 | is-plain-obj "^1.1.0" 1229 | 1230 | minimist-options@^4.0.2: 1231 | version "4.1.0" 1232 | resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" 1233 | dependencies: 1234 | arrify "^1.0.1" 1235 | is-plain-obj "^1.1.0" 1236 | kind-of "^6.0.3" 1237 | 1238 | minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: 1239 | version "1.2.5" 1240 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 1241 | 1242 | modify-values@^1.0.0: 1243 | version "1.0.1" 1244 | resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" 1245 | 1246 | mount-point@^3.0.0: 1247 | version "3.0.0" 1248 | resolved "https://registry.yarnpkg.com/mount-point/-/mount-point-3.0.0.tgz#665cb9edebe80d110e658db56c31d0aef51a8f97" 1249 | dependencies: 1250 | "@sindresorhus/df" "^1.0.1" 1251 | pify "^2.3.0" 1252 | pinkie-promise "^2.0.1" 1253 | 1254 | move-file@^1.1.0: 1255 | version "1.2.0" 1256 | resolved "https://registry.yarnpkg.com/move-file/-/move-file-1.2.0.tgz#789f92d276c62511d214b1b285aa16e015c2f2fc" 1257 | dependencies: 1258 | cp-file "^6.1.0" 1259 | make-dir "^3.0.0" 1260 | path-exists "^3.0.0" 1261 | 1262 | neo-async@^2.6.0: 1263 | version "2.6.1" 1264 | resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" 1265 | 1266 | nested-error-stacks@^2.0.0: 1267 | version "2.1.0" 1268 | resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61" 1269 | 1270 | normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.5.0: 1271 | version "2.5.0" 1272 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 1273 | dependencies: 1274 | hosted-git-info "^2.1.4" 1275 | resolve "^1.10.0" 1276 | semver "2 || 3 || 4 || 5" 1277 | validate-npm-package-license "^3.0.1" 1278 | 1279 | normalize-url@^4.1.0: 1280 | version "4.5.0" 1281 | resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" 1282 | 1283 | npm-run-path@^1.0.0: 1284 | version "1.0.0" 1285 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-1.0.0.tgz#f5c32bf595fe81ae927daec52e82f8b000ac3c8f" 1286 | dependencies: 1287 | path-key "^1.0.0" 1288 | 1289 | npm-run-path@^2.0.0: 1290 | version "2.0.2" 1291 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 1292 | dependencies: 1293 | path-key "^2.0.0" 1294 | 1295 | null-check@^1.0.0: 1296 | version "1.0.0" 1297 | resolved "https://registry.yarnpkg.com/null-check/-/null-check-1.0.0.tgz#977dffd7176012b9ec30d2a39db5cf72a0439edd" 1298 | 1299 | number-is-nan@^1.0.0: 1300 | version "1.0.1" 1301 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 1302 | 1303 | object-assign@^4.0.1: 1304 | version "4.1.1" 1305 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 1306 | 1307 | once@^1.3.0, once@^1.3.1, once@^1.4.0: 1308 | version "1.4.0" 1309 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 1310 | dependencies: 1311 | wrappy "1" 1312 | 1313 | open-cli@^5.0.0: 1314 | version "5.0.0" 1315 | resolved "https://registry.yarnpkg.com/open-cli/-/open-cli-5.0.0.tgz#fc8286ac11bad487a7798b4fb19561839420eebf" 1316 | dependencies: 1317 | file-type "^11.0.0" 1318 | get-stdin "^7.0.0" 1319 | meow "^5.0.0" 1320 | open "^6.3.0" 1321 | temp-write "^4.0.0" 1322 | 1323 | open@^6.3.0: 1324 | version "6.4.0" 1325 | resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" 1326 | dependencies: 1327 | is-wsl "^1.1.0" 1328 | 1329 | os-homedir@^1.0.0: 1330 | version "1.0.2" 1331 | resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" 1332 | 1333 | p-cancelable@^1.0.0: 1334 | version "1.1.0" 1335 | resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" 1336 | 1337 | p-finally@^1.0.0: 1338 | version "1.0.0" 1339 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 1340 | 1341 | p-limit@^1.1.0: 1342 | version "1.3.0" 1343 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" 1344 | dependencies: 1345 | p-try "^1.0.0" 1346 | 1347 | p-limit@^2.0.0, p-limit@^2.2.0: 1348 | version "2.3.0" 1349 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 1350 | dependencies: 1351 | p-try "^2.0.0" 1352 | 1353 | p-locate@^2.0.0: 1354 | version "2.0.0" 1355 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" 1356 | dependencies: 1357 | p-limit "^1.1.0" 1358 | 1359 | p-locate@^3.0.0: 1360 | version "3.0.0" 1361 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" 1362 | dependencies: 1363 | p-limit "^2.0.0" 1364 | 1365 | p-locate@^4.1.0: 1366 | version "4.1.0" 1367 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 1368 | dependencies: 1369 | p-limit "^2.2.0" 1370 | 1371 | p-map@^3.0.0: 1372 | version "3.0.0" 1373 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" 1374 | dependencies: 1375 | aggregate-error "^3.0.0" 1376 | 1377 | p-try@^1.0.0: 1378 | version "1.0.0" 1379 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" 1380 | 1381 | p-try@^2.0.0, p-try@^2.2.0: 1382 | version "2.2.0" 1383 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 1384 | 1385 | package-json@^6.3.0: 1386 | version "6.5.0" 1387 | resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" 1388 | dependencies: 1389 | got "^9.6.0" 1390 | registry-auth-token "^4.0.0" 1391 | registry-url "^5.0.0" 1392 | semver "^6.2.0" 1393 | 1394 | paper@^0.12.11: 1395 | version "0.12.11" 1396 | resolved "https://registry.yarnpkg.com/paper/-/paper-0.12.11.tgz#21914ab0bbef939241ace5e4c87ff2543e7c8b7d" 1397 | 1398 | parse-github-repo-url@^1.3.0: 1399 | version "1.4.1" 1400 | resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" 1401 | 1402 | parse-json@^2.2.0: 1403 | version "2.2.0" 1404 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" 1405 | dependencies: 1406 | error-ex "^1.2.0" 1407 | 1408 | parse-json@^4.0.0: 1409 | version "4.0.0" 1410 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 1411 | dependencies: 1412 | error-ex "^1.3.1" 1413 | json-parse-better-errors "^1.0.1" 1414 | 1415 | parse-json@^5.0.0: 1416 | version "5.0.0" 1417 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.0.0.tgz#73e5114c986d143efa3712d4ea24db9a4266f60f" 1418 | dependencies: 1419 | "@babel/code-frame" "^7.0.0" 1420 | error-ex "^1.3.1" 1421 | json-parse-better-errors "^1.0.1" 1422 | lines-and-columns "^1.1.6" 1423 | 1424 | path-exists@^2.0.0: 1425 | version "2.1.0" 1426 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" 1427 | dependencies: 1428 | pinkie-promise "^2.0.0" 1429 | 1430 | path-exists@^3.0.0: 1431 | version "3.0.0" 1432 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 1433 | 1434 | path-exists@^4.0.0: 1435 | version "4.0.0" 1436 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1437 | 1438 | path-is-absolute@^1.0.0: 1439 | version "1.0.1" 1440 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1441 | 1442 | path-is-inside@^1.0.1: 1443 | version "1.0.2" 1444 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 1445 | 1446 | path-key@^1.0.0: 1447 | version "1.0.0" 1448 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-1.0.0.tgz#5d53d578019646c0d68800db4e146e6bdc2ac7af" 1449 | 1450 | path-key@^2.0.0: 1451 | version "2.0.1" 1452 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 1453 | 1454 | path-parse@^1.0.6: 1455 | version "1.0.6" 1456 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 1457 | 1458 | path-type@^1.0.0: 1459 | version "1.1.0" 1460 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" 1461 | dependencies: 1462 | graceful-fs "^4.1.2" 1463 | pify "^2.0.0" 1464 | pinkie-promise "^2.0.0" 1465 | 1466 | path-type@^3.0.0: 1467 | version "3.0.0" 1468 | resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" 1469 | dependencies: 1470 | pify "^3.0.0" 1471 | 1472 | pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: 1473 | version "2.3.0" 1474 | resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" 1475 | 1476 | pify@^3.0.0: 1477 | version "3.0.0" 1478 | resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" 1479 | 1480 | pify@^4.0.1: 1481 | version "4.0.1" 1482 | resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" 1483 | 1484 | pinkie-promise@^2.0.0, pinkie-promise@^2.0.1: 1485 | version "2.0.1" 1486 | resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" 1487 | dependencies: 1488 | pinkie "^2.0.0" 1489 | 1490 | pinkie@^2.0.0: 1491 | version "2.0.4" 1492 | resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" 1493 | 1494 | prepend-http@^2.0.0: 1495 | version "2.0.0" 1496 | resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" 1497 | 1498 | process-nextick-args@~2.0.0: 1499 | version "2.0.1" 1500 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 1501 | 1502 | progress@^2.0.3: 1503 | version "2.0.3" 1504 | resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" 1505 | 1506 | pseudomap@^1.0.2: 1507 | version "1.0.2" 1508 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" 1509 | 1510 | pump@^3.0.0: 1511 | version "3.0.0" 1512 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 1513 | dependencies: 1514 | end-of-stream "^1.1.0" 1515 | once "^1.3.1" 1516 | 1517 | q@^1.5.1: 1518 | version "1.5.1" 1519 | resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" 1520 | 1521 | quick-lru@^1.0.0: 1522 | version "1.1.0" 1523 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" 1524 | 1525 | quick-lru@^4.0.1: 1526 | version "4.0.1" 1527 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" 1528 | 1529 | rc@^1.2.8: 1530 | version "1.2.8" 1531 | resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" 1532 | dependencies: 1533 | deep-extend "^0.6.0" 1534 | ini "~1.3.0" 1535 | minimist "^1.2.0" 1536 | strip-json-comments "~2.0.1" 1537 | 1538 | read-pkg-up@^1.0.1: 1539 | version "1.0.1" 1540 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" 1541 | dependencies: 1542 | find-up "^1.0.0" 1543 | read-pkg "^1.0.0" 1544 | 1545 | read-pkg-up@^3.0.0: 1546 | version "3.0.0" 1547 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" 1548 | dependencies: 1549 | find-up "^2.0.0" 1550 | read-pkg "^3.0.0" 1551 | 1552 | read-pkg-up@^7.0.1: 1553 | version "7.0.1" 1554 | resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" 1555 | dependencies: 1556 | find-up "^4.1.0" 1557 | read-pkg "^5.2.0" 1558 | type-fest "^0.8.1" 1559 | 1560 | read-pkg@^1.0.0: 1561 | version "1.1.0" 1562 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" 1563 | dependencies: 1564 | load-json-file "^1.0.0" 1565 | normalize-package-data "^2.3.2" 1566 | path-type "^1.0.0" 1567 | 1568 | read-pkg@^3.0.0: 1569 | version "3.0.0" 1570 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" 1571 | dependencies: 1572 | load-json-file "^4.0.0" 1573 | normalize-package-data "^2.3.2" 1574 | path-type "^3.0.0" 1575 | 1576 | read-pkg@^5.2.0: 1577 | version "5.2.0" 1578 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" 1579 | dependencies: 1580 | "@types/normalize-package-data" "^2.4.0" 1581 | normalize-package-data "^2.5.0" 1582 | parse-json "^5.0.0" 1583 | type-fest "^0.6.0" 1584 | 1585 | "readable-stream@2 || 3", readable-stream@^3.0.2: 1586 | version "3.6.0" 1587 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" 1588 | dependencies: 1589 | inherits "^2.0.3" 1590 | string_decoder "^1.1.1" 1591 | util-deprecate "^1.0.1" 1592 | 1593 | readable-stream@~2.3.6: 1594 | version "2.3.7" 1595 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" 1596 | dependencies: 1597 | core-util-is "~1.0.0" 1598 | inherits "~2.0.3" 1599 | isarray "~1.0.0" 1600 | process-nextick-args "~2.0.0" 1601 | safe-buffer "~5.1.1" 1602 | string_decoder "~1.1.1" 1603 | util-deprecate "~1.0.1" 1604 | 1605 | rechoir@^0.6.2: 1606 | version "0.6.2" 1607 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" 1608 | dependencies: 1609 | resolve "^1.1.6" 1610 | 1611 | redent@^1.0.0: 1612 | version "1.0.0" 1613 | resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" 1614 | dependencies: 1615 | indent-string "^2.1.0" 1616 | strip-indent "^1.0.1" 1617 | 1618 | redent@^2.0.0: 1619 | version "2.0.0" 1620 | resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" 1621 | dependencies: 1622 | indent-string "^3.0.0" 1623 | strip-indent "^2.0.0" 1624 | 1625 | redent@^3.0.0: 1626 | version "3.0.0" 1627 | resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" 1628 | dependencies: 1629 | indent-string "^4.0.0" 1630 | strip-indent "^3.0.0" 1631 | 1632 | registry-auth-token@^4.0.0: 1633 | version "4.1.1" 1634 | resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479" 1635 | dependencies: 1636 | rc "^1.2.8" 1637 | 1638 | registry-url@^5.0.0: 1639 | version "5.1.0" 1640 | resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009" 1641 | dependencies: 1642 | rc "^1.2.8" 1643 | 1644 | repeating@^2.0.0: 1645 | version "2.0.1" 1646 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" 1647 | dependencies: 1648 | is-finite "^1.0.0" 1649 | 1650 | require-directory@^2.1.1: 1651 | version "2.1.1" 1652 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" 1653 | 1654 | require-main-filename@^2.0.0: 1655 | version "2.0.0" 1656 | resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" 1657 | 1658 | resolve@^1.1.6, resolve@^1.10.0: 1659 | version "1.17.0" 1660 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" 1661 | dependencies: 1662 | path-parse "^1.0.6" 1663 | 1664 | responselike@^1.0.2: 1665 | version "1.0.2" 1666 | resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" 1667 | dependencies: 1668 | lowercase-keys "^1.0.0" 1669 | 1670 | safe-buffer@^5.0.1, safe-buffer@~5.2.0: 1671 | version "5.2.1" 1672 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" 1673 | 1674 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1675 | version "5.1.2" 1676 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1677 | 1678 | semver-diff@^2.0.0: 1679 | version "2.1.0" 1680 | resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" 1681 | dependencies: 1682 | semver "^5.0.3" 1683 | 1684 | "semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.6.0: 1685 | version "5.7.1" 1686 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 1687 | 1688 | semver@^6.0.0, semver@^6.2.0: 1689 | version "6.3.0" 1690 | resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" 1691 | 1692 | semver@^7.1.1: 1693 | version "7.3.2" 1694 | resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" 1695 | 1696 | set-blocking@^2.0.0: 1697 | version "2.0.0" 1698 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 1699 | 1700 | shebang-command@^1.2.0: 1701 | version "1.2.0" 1702 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 1703 | dependencies: 1704 | shebang-regex "^1.0.0" 1705 | 1706 | shebang-regex@^1.0.0: 1707 | version "1.0.0" 1708 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 1709 | 1710 | shelljs@^0.8.3: 1711 | version "0.8.4" 1712 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" 1713 | dependencies: 1714 | glob "^7.0.0" 1715 | interpret "^1.0.0" 1716 | rechoir "^0.6.2" 1717 | 1718 | signal-exit@^3.0.0, signal-exit@^3.0.2: 1719 | version "3.0.3" 1720 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 1721 | 1722 | slash@^1.0.0: 1723 | version "1.0.0" 1724 | resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" 1725 | 1726 | source-map@^0.6.1: 1727 | version "0.6.1" 1728 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1729 | 1730 | spdx-correct@^3.0.0: 1731 | version "3.1.1" 1732 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" 1733 | dependencies: 1734 | spdx-expression-parse "^3.0.0" 1735 | spdx-license-ids "^3.0.0" 1736 | 1737 | spdx-exceptions@^2.1.0: 1738 | version "2.3.0" 1739 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" 1740 | 1741 | spdx-expression-parse@^3.0.0: 1742 | version "3.0.1" 1743 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" 1744 | dependencies: 1745 | spdx-exceptions "^2.1.0" 1746 | spdx-license-ids "^3.0.0" 1747 | 1748 | spdx-license-ids@^3.0.0: 1749 | version "3.0.5" 1750 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" 1751 | 1752 | split2@^2.0.0: 1753 | version "2.2.0" 1754 | resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" 1755 | dependencies: 1756 | through2 "^2.0.2" 1757 | 1758 | split@^1.0.0: 1759 | version "1.0.1" 1760 | resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" 1761 | dependencies: 1762 | through "2" 1763 | 1764 | standard-version@^8.0.1: 1765 | version "8.0.1" 1766 | resolved "https://registry.yarnpkg.com/standard-version/-/standard-version-8.0.1.tgz#4638d3cee1365c9d6773c3ac33429e4562f3f696" 1767 | dependencies: 1768 | chalk "^2.4.2" 1769 | conventional-changelog "3.1.21" 1770 | conventional-changelog-config-spec "2.1.0" 1771 | conventional-changelog-conventionalcommits "4.3.0" 1772 | conventional-recommended-bump "6.0.9" 1773 | detect-indent "^6.0.0" 1774 | detect-newline "^3.1.0" 1775 | dotgitignore "^2.1.0" 1776 | figures "^3.1.0" 1777 | find-up "^4.1.0" 1778 | fs-access "^1.0.1" 1779 | git-semver-tags "^4.0.0" 1780 | semver "^7.1.1" 1781 | stringify-package "^1.0.1" 1782 | yargs "^15.3.1" 1783 | 1784 | string-width@^2.1.1: 1785 | version "2.1.1" 1786 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 1787 | dependencies: 1788 | is-fullwidth-code-point "^2.0.0" 1789 | strip-ansi "^4.0.0" 1790 | 1791 | string-width@^3.0.0: 1792 | version "3.1.0" 1793 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" 1794 | dependencies: 1795 | emoji-regex "^7.0.1" 1796 | is-fullwidth-code-point "^2.0.0" 1797 | strip-ansi "^5.1.0" 1798 | 1799 | string-width@^4.1.0, string-width@^4.2.0: 1800 | version "4.2.0" 1801 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" 1802 | dependencies: 1803 | emoji-regex "^8.0.0" 1804 | is-fullwidth-code-point "^3.0.0" 1805 | strip-ansi "^6.0.0" 1806 | 1807 | string_decoder@^1.1.1: 1808 | version "1.3.0" 1809 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" 1810 | dependencies: 1811 | safe-buffer "~5.2.0" 1812 | 1813 | string_decoder@~1.1.1: 1814 | version "1.1.1" 1815 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 1816 | dependencies: 1817 | safe-buffer "~5.1.0" 1818 | 1819 | stringify-package@^1.0.1: 1820 | version "1.0.1" 1821 | resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85" 1822 | 1823 | strip-ansi@^4.0.0: 1824 | version "4.0.0" 1825 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 1826 | dependencies: 1827 | ansi-regex "^3.0.0" 1828 | 1829 | strip-ansi@^5.1.0: 1830 | version "5.2.0" 1831 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" 1832 | dependencies: 1833 | ansi-regex "^4.1.0" 1834 | 1835 | strip-ansi@^6.0.0: 1836 | version "6.0.0" 1837 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" 1838 | dependencies: 1839 | ansi-regex "^5.0.0" 1840 | 1841 | strip-bom@^2.0.0: 1842 | version "2.0.0" 1843 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" 1844 | dependencies: 1845 | is-utf8 "^0.2.0" 1846 | 1847 | strip-bom@^3.0.0: 1848 | version "3.0.0" 1849 | resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" 1850 | 1851 | strip-eof@^1.0.0: 1852 | version "1.0.0" 1853 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 1854 | 1855 | strip-indent@^1.0.1: 1856 | version "1.0.1" 1857 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" 1858 | dependencies: 1859 | get-stdin "^4.0.1" 1860 | 1861 | strip-indent@^2.0.0: 1862 | version "2.0.0" 1863 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" 1864 | 1865 | strip-indent@^3.0.0: 1866 | version "3.0.0" 1867 | resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" 1868 | dependencies: 1869 | min-indent "^1.0.0" 1870 | 1871 | strip-json-comments@~2.0.1: 1872 | version "2.0.1" 1873 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1874 | 1875 | supports-color@^5.3.0: 1876 | version "5.5.0" 1877 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1878 | dependencies: 1879 | has-flag "^3.0.0" 1880 | 1881 | temp-dir@^1.0.0: 1882 | version "1.0.0" 1883 | resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" 1884 | 1885 | temp-write@^4.0.0: 1886 | version "4.0.0" 1887 | resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-4.0.0.tgz#cd2e0825fc826ae72d201dc26eef3bf7e6fc9320" 1888 | dependencies: 1889 | graceful-fs "^4.1.15" 1890 | is-stream "^2.0.0" 1891 | make-dir "^3.0.0" 1892 | temp-dir "^1.0.0" 1893 | uuid "^3.3.2" 1894 | 1895 | term-size@^1.2.0: 1896 | version "1.2.0" 1897 | resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" 1898 | dependencies: 1899 | execa "^0.7.0" 1900 | 1901 | text-extensions@^1.0.0: 1902 | version "1.9.0" 1903 | resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" 1904 | 1905 | through2@^2.0.0, through2@^2.0.2: 1906 | version "2.0.5" 1907 | resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" 1908 | dependencies: 1909 | readable-stream "~2.3.6" 1910 | xtend "~4.0.1" 1911 | 1912 | through2@^3.0.0: 1913 | version "3.0.1" 1914 | resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" 1915 | dependencies: 1916 | readable-stream "2 || 3" 1917 | 1918 | through@2, "through@>=2.2.7 <3": 1919 | version "2.3.8" 1920 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1921 | 1922 | to-readable-stream@^1.0.0: 1923 | version "1.0.0" 1924 | resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" 1925 | 1926 | trash-cli@^3.0.0: 1927 | version "3.0.0" 1928 | resolved "https://registry.yarnpkg.com/trash-cli/-/trash-cli-3.0.0.tgz#6a0deb41e45f7cfe3aa18437d5d60d632fa26d4f" 1929 | dependencies: 1930 | meow "^3.7.0" 1931 | trash "^6.0.0" 1932 | update-notifier "^3.0.0" 1933 | 1934 | trash@^6.0.0: 1935 | version "6.1.1" 1936 | resolved "https://registry.yarnpkg.com/trash/-/trash-6.1.1.tgz#8fb863421b31f32571f2650b53534934d5e63025" 1937 | dependencies: 1938 | "@stroncium/procfs" "^1.0.0" 1939 | globby "^7.1.1" 1940 | is-path-inside "^3.0.2" 1941 | make-dir "^3.0.0" 1942 | move-file "^1.1.0" 1943 | p-map "^3.0.0" 1944 | p-try "^2.2.0" 1945 | uuid "^3.3.2" 1946 | xdg-trashdir "^2.1.1" 1947 | 1948 | trim-newlines@^1.0.0: 1949 | version "1.0.0" 1950 | resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" 1951 | 1952 | trim-newlines@^2.0.0: 1953 | version "2.0.0" 1954 | resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" 1955 | 1956 | trim-newlines@^3.0.0: 1957 | version "3.0.0" 1958 | resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" 1959 | 1960 | trim-off-newlines@^1.0.0: 1961 | version "1.0.1" 1962 | resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" 1963 | 1964 | type-fest@^0.13.1: 1965 | version "0.13.1" 1966 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" 1967 | 1968 | type-fest@^0.3.0: 1969 | version "0.3.1" 1970 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" 1971 | 1972 | type-fest@^0.6.0: 1973 | version "0.6.0" 1974 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" 1975 | 1976 | type-fest@^0.8.1: 1977 | version "0.8.1" 1978 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" 1979 | 1980 | typedarray@^0.0.6: 1981 | version "0.0.6" 1982 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 1983 | 1984 | typedoc-default-themes@^0.6.0-0: 1985 | version "0.6.3" 1986 | resolved "https://registry.yarnpkg.com/typedoc-default-themes/-/typedoc-default-themes-0.6.3.tgz#c214ce5bbcc6045558448a8fd422b90e3e9b6782" 1987 | dependencies: 1988 | backbone "^1.4.0" 1989 | jquery "^3.4.1" 1990 | lunr "^2.3.8" 1991 | underscore "^1.9.1" 1992 | 1993 | typescript@3.5.x: 1994 | version "3.5.3" 1995 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" 1996 | 1997 | uglify-js@^3.1.4: 1998 | version "3.10.0" 1999 | resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.10.0.tgz#397a7e6e31ce820bfd1cb55b804ee140c587a9e7" 2000 | 2001 | underscore@>=1.8.3, underscore@^1.9.1: 2002 | version "1.10.2" 2003 | resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.10.2.tgz#73d6aa3668f3188e4adb0f1943bd12cfd7efaaaf" 2004 | 2005 | unique-string@^1.0.0: 2006 | version "1.0.0" 2007 | resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" 2008 | dependencies: 2009 | crypto-random-string "^1.0.0" 2010 | 2011 | universalify@^0.1.0: 2012 | version "0.1.2" 2013 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" 2014 | 2015 | unquote@^1.1.0: 2016 | version "1.1.1" 2017 | resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" 2018 | 2019 | update-notifier@^3.0.0: 2020 | version "3.0.1" 2021 | resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-3.0.1.tgz#78ecb68b915e2fd1be9f767f6e298ce87b736250" 2022 | dependencies: 2023 | boxen "^3.0.0" 2024 | chalk "^2.0.1" 2025 | configstore "^4.0.0" 2026 | has-yarn "^2.1.0" 2027 | import-lazy "^2.1.0" 2028 | is-ci "^2.0.0" 2029 | is-installed-globally "^0.1.0" 2030 | is-npm "^3.0.0" 2031 | is-yarn-global "^0.3.0" 2032 | latest-version "^5.0.0" 2033 | semver-diff "^2.0.0" 2034 | xdg-basedir "^3.0.0" 2035 | 2036 | url-parse-lax@^3.0.0: 2037 | version "3.0.0" 2038 | resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" 2039 | dependencies: 2040 | prepend-http "^2.0.0" 2041 | 2042 | user-home@^2.0.0: 2043 | version "2.0.0" 2044 | resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" 2045 | dependencies: 2046 | os-homedir "^1.0.0" 2047 | 2048 | util-deprecate@^1.0.1, util-deprecate@~1.0.1: 2049 | version "1.0.2" 2050 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 2051 | 2052 | uuid@^3.3.2: 2053 | version "3.4.0" 2054 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 2055 | 2056 | validate-npm-package-license@^3.0.1: 2057 | version "3.0.4" 2058 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 2059 | dependencies: 2060 | spdx-correct "^3.0.0" 2061 | spdx-expression-parse "^3.0.0" 2062 | 2063 | which-module@^2.0.0: 2064 | version "2.0.0" 2065 | resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" 2066 | 2067 | which@^1.2.8, which@^1.2.9: 2068 | version "1.3.1" 2069 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 2070 | dependencies: 2071 | isexe "^2.0.0" 2072 | 2073 | widest-line@^2.0.0: 2074 | version "2.0.1" 2075 | resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" 2076 | dependencies: 2077 | string-width "^2.1.1" 2078 | 2079 | wordwrap@^1.0.0: 2080 | version "1.0.0" 2081 | resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" 2082 | 2083 | wrap-ansi@^6.2.0: 2084 | version "6.2.0" 2085 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" 2086 | dependencies: 2087 | ansi-styles "^4.0.0" 2088 | string-width "^4.1.0" 2089 | strip-ansi "^6.0.0" 2090 | 2091 | wrappy@1: 2092 | version "1.0.2" 2093 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 2094 | 2095 | write-file-atomic@^2.0.0: 2096 | version "2.4.3" 2097 | resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" 2098 | dependencies: 2099 | graceful-fs "^4.1.11" 2100 | imurmurhash "^0.1.4" 2101 | signal-exit "^3.0.2" 2102 | 2103 | xdg-basedir@^2.0.0: 2104 | version "2.0.0" 2105 | resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2" 2106 | dependencies: 2107 | os-homedir "^1.0.0" 2108 | 2109 | xdg-basedir@^3.0.0: 2110 | version "3.0.0" 2111 | resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" 2112 | 2113 | xdg-trashdir@^2.1.1: 2114 | version "2.1.1" 2115 | resolved "https://registry.yarnpkg.com/xdg-trashdir/-/xdg-trashdir-2.1.1.tgz#59a60aaf8e6f9240c1daed9a0944b2f514c27d8e" 2116 | dependencies: 2117 | "@sindresorhus/df" "^2.1.0" 2118 | mount-point "^3.0.0" 2119 | pify "^2.2.0" 2120 | user-home "^2.0.0" 2121 | xdg-basedir "^2.0.0" 2122 | 2123 | xtend@~4.0.1: 2124 | version "4.0.2" 2125 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 2126 | 2127 | y18n@^4.0.0: 2128 | version "4.0.0" 2129 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" 2130 | 2131 | yallist@^2.1.2: 2132 | version "2.1.2" 2133 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" 2134 | 2135 | yargs-parser@^10.0.0: 2136 | version "10.1.0" 2137 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" 2138 | dependencies: 2139 | camelcase "^4.1.0" 2140 | 2141 | yargs-parser@^18.1.1, yargs-parser@^18.1.3: 2142 | version "18.1.3" 2143 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" 2144 | dependencies: 2145 | camelcase "^5.0.0" 2146 | decamelize "^1.2.0" 2147 | 2148 | yargs@^15.3.1: 2149 | version "15.3.1" 2150 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b" 2151 | dependencies: 2152 | cliui "^6.0.0" 2153 | decamelize "^1.2.0" 2154 | find-up "^4.1.0" 2155 | get-caller-file "^2.0.1" 2156 | require-directory "^2.1.1" 2157 | require-main-filename "^2.0.0" 2158 | set-blocking "^2.0.0" 2159 | string-width "^4.2.0" 2160 | which-module "^2.0.0" 2161 | y18n "^4.0.0" 2162 | yargs-parser "^18.1.1" 2163 | -------------------------------------------------------------------------------- /src/assets/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/assets/icon128.png -------------------------------------------------------------------------------- /src/assets/icon128.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/assets/icon128.psd -------------------------------------------------------------------------------- /src/assets/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/assets/icon16.png -------------------------------------------------------------------------------- /src/assets/icon16.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/assets/icon16.psd -------------------------------------------------------------------------------- /src/assets/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/assets/icon48.png -------------------------------------------------------------------------------- /src/assets/icon48.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/assets/icon48.psd -------------------------------------------------------------------------------- /src/background.ts: -------------------------------------------------------------------------------- 1 | import { injectable } from 'inversify'; 2 | import 'reflect-metadata'; 3 | import 'regenerator-runtime/runtime'; 4 | import { 5 | CapturedTab, 6 | container, 7 | ContentInjector, 8 | MessageService, 9 | toPromise, 10 | } from '~/common'; 11 | 12 | @injectable() 13 | class BackgroundMain { 14 | constructor( 15 | private messageService: MessageService, 16 | private contentInjector: ContentInjector, 17 | ) { 18 | chrome.runtime.onInstalled.addListener(() => { 19 | console.log('AnyColor installed.'); 20 | }); 21 | 22 | this.messageService.on('requestCapture', this.captureVisibleTab); 23 | this.handleCommands(); 24 | this.handleBrowserAction(); 25 | } 26 | 27 | private captureVisibleTab = async (): Promise => { 28 | const tabs = await toPromise(chrome.tabs.query)({ 29 | active: true, 30 | currentWindow: true, 31 | }); 32 | const latestTab = tabs[0]; 33 | const zoom: number = await toPromise(chrome.tabs.getZoom)(); 34 | const width = latestTab.width / zoom; 35 | const height = latestTab.height / zoom; 36 | 37 | const imgSrc = await toPromise(chrome.tabs.captureVisibleTab)( 38 | null, 39 | { 40 | format: 'png', 41 | }, 42 | ); 43 | 44 | const capturedTab = { 45 | imgSrc, 46 | width, 47 | height, 48 | }; 49 | console.log('captureVisibleTab:', capturedTab); 50 | return capturedTab; 51 | }; 52 | 53 | private handleCommands() { 54 | chrome.commands.onCommand.addListener(async (command: string) => { 55 | if (command === 'toggle-inspector') { 56 | const tabId = await this.contentInjector.getActiveTabId(); 57 | this.toggleInspector(tabId); 58 | } 59 | }); 60 | } 61 | 62 | private handleBrowserAction() { 63 | chrome.action.onClicked.addListener(({ id }) => { 64 | this.toggleInspector(id); 65 | }); 66 | } 67 | 68 | /** 69 | * @remarks 70 | * Ensure content script is injected and send message to the active tab. 71 | */ 72 | private async toggleInspector(tabId: number) { 73 | await this.contentInjector.inject(tabId); 74 | this.messageService.sendTab('toggleInspector'); 75 | } 76 | } 77 | 78 | container.bind(BackgroundMain).toSelf(); 79 | container.bind(ContentInjector).toSelf(); 80 | container.resolve(BackgroundMain); 81 | -------------------------------------------------------------------------------- /src/common/content-injector.ts: -------------------------------------------------------------------------------- 1 | import { injectable } from 'inversify'; 2 | import { toPromise } from '~/common'; 3 | import 'reflect-metadata'; 4 | 5 | @injectable() 6 | export class ContentInjector { 7 | public async inject(tabId: number): Promise { 8 | const isInjected = await this.isInjected(tabId); 9 | if (isInjected) { 10 | return; 11 | } 12 | 13 | return toPromise(chrome.scripting.executeScript)({ 14 | target: { tabId }, 15 | files: ['content.js'], 16 | }); 17 | } 18 | 19 | public async getActiveTabId(): Promise { 20 | const tabs = await toPromise(chrome.tabs.query)({ 21 | active: true, 22 | currentWindow: true, 23 | }); 24 | return tabs[0].id; 25 | } 26 | 27 | private runCode() { 28 | const a = document.querySelector('ac-root'); 29 | return a ? true : null; 30 | } 31 | 32 | private async isInjected(tabId: number) { 33 | const results = await toPromise(chrome.scripting.executeScript)({ 34 | target: { tabId }, 35 | func: this.runCode, 36 | }); 37 | 38 | return results[0].result; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/common/index.ts: -------------------------------------------------------------------------------- 1 | export * from './inversify.config'; 2 | export * from './message-service'; 3 | export * from './utils'; 4 | export * from './models'; 5 | export * from './content-injector'; 6 | -------------------------------------------------------------------------------- /src/common/inversify.config.ts: -------------------------------------------------------------------------------- 1 | import { Container } from 'inversify'; 2 | import getDecorators from 'inversify-inject-decorators'; 3 | import { MessageService } from './message-service'; 4 | 5 | const container = new Container(); 6 | container.bind(MessageService).toSelf(); 7 | 8 | const { lazyInject } = getDecorators(container); 9 | 10 | export { container, lazyInject }; 11 | -------------------------------------------------------------------------------- /src/common/message-service.ts: -------------------------------------------------------------------------------- 1 | import { injectable } from 'inversify'; 2 | import { toPromise } from './utils'; 3 | import 'reflect-metadata'; 4 | 5 | interface EventPayload { 6 | eventName: string; 7 | detail?: EventDetail; 8 | } 9 | 10 | type EventCallback = (detail: EventDetail) => T | Promise; 11 | 12 | export type EventDetail = {}; 13 | 14 | @injectable() 15 | export class MessageService { 16 | private eventMap: { 17 | [eventName: string]: EventCallback; 18 | } = {}; 19 | 20 | constructor() { 21 | this.handleMessages(); 22 | } 23 | 24 | /** 25 | * Send message to a {@link chrome.tabs.Tab}. 26 | */ 27 | public async sendTab(eventName: string, detail = {}): Promise { 28 | if (!chrome.tabs) { 29 | return Promise.resolve(null); 30 | } 31 | 32 | const tabs = await toPromise(chrome.tabs.query)({ 33 | active: true, 34 | currentWindow: true, 35 | }); 36 | 37 | return toPromise(chrome.tabs.sendMessage)(tabs[0].id, { 38 | eventName, 39 | detail, 40 | } as EventPayload); 41 | } 42 | 43 | /** 44 | * Send message to runtime (background script). 45 | */ 46 | public async send(eventName: string, detail = {}): Promise { 47 | return toPromise(chrome.runtime.sendMessage)({ 48 | eventName, 49 | detail, 50 | } as EventPayload); 51 | } 52 | 53 | public on(eventName: string, callback: EventCallback) { 54 | this.eventMap[eventName] = callback; 55 | } 56 | 57 | private handleMessages() { 58 | if (!chrome.runtime.onMessage) { 59 | return; 60 | } 61 | chrome.runtime.onMessage.addListener( 62 | (payload: EventPayload, _sender, sendResponse) => { 63 | const callback = this.eventMap[payload.eventName]; 64 | if (callback) { 65 | Promise.resolve(callback(payload.detail)).then((result) => { 66 | sendResponse(result); 67 | }); 68 | } 69 | // keep the connection open during the async execution 70 | return true; 71 | } 72 | ); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/common/models.ts: -------------------------------------------------------------------------------- 1 | export interface CapturedTab { 2 | imgSrc: string; 3 | width: number; 4 | height: number; 5 | } 6 | -------------------------------------------------------------------------------- /src/common/utils.ts: -------------------------------------------------------------------------------- 1 | export function toPromise(callback) { 2 | return (...args): Promise => { 3 | return new Promise((resolve) => { 4 | callback(...args, resolve); 5 | }); 6 | }; 7 | } 8 | 9 | /** 10 | * Helper for copying text to system clipboard. 11 | */ 12 | export function copy(text: string) { 13 | const input = document.createElement('textarea'); 14 | input.innerHTML = text; 15 | document.body.appendChild(input); 16 | input.select(); 17 | const result = document.execCommand('copy'); 18 | document.body.removeChild(input); 19 | return result; 20 | } 21 | -------------------------------------------------------------------------------- /src/content.ts: -------------------------------------------------------------------------------- 1 | import '@webcomponents/webcomponentsjs/webcomponents-bundle'; 2 | import { Inspector, inspectorFactory } from 'colorins'; 3 | import 'regenerator-runtime/runtime'; 4 | import { AppManager } from './core'; 5 | import { container } from '~/common'; 6 | import { App, Snackbar, snackbarFactory } from '~/elements'; 7 | 8 | const dom = document.createElement('ac-root'); 9 | document.body.insertAdjacentElement('afterbegin', dom); 10 | 11 | const canvas = document.createElement('canvas'); 12 | const afterInjected = dom.injectCanvas(canvas).then(() => { 13 | container.bind(App).toConstantValue(dom); 14 | container.bind(AppManager).toSelf(); 15 | container 16 | .bind(Inspector) 17 | .toConstantValue(inspectorFactory(canvas)); 18 | container.bind(Snackbar).toConstantValue(snackbarFactory(dom)); 19 | return container.resolve(AppManager); 20 | }); 21 | 22 | export { afterInjected }; 23 | -------------------------------------------------------------------------------- /src/core/app-manager.test.ts: -------------------------------------------------------------------------------- 1 | import { AppManager } from './app-manager'; 2 | import { container, MessageService } from '~/common'; 3 | import { afterInjected } from '~/content'; 4 | import { App } from '~/elements'; 5 | 6 | describe('AppManager', () => { 7 | let appManager: AppManager; 8 | let app: App; 9 | let messageService: MessageService; 10 | 11 | beforeAll(async () => { 12 | appManager = await afterInjected; 13 | app = container.get(App); 14 | messageService = container.get(MessageService); 15 | }); 16 | 17 | it('should create a AppManager instance', () => { 18 | expect(appManager).toBeTruthy(); 19 | }); 20 | 21 | it('app should be invisible when boot', () => { 22 | expect(app.visible).toBeFalsy(); 23 | }); 24 | 25 | it('should toggle app by message, from visible to invisible', async () => { 26 | app.show(); 27 | expect(app.visible).toBe(true); 28 | await messageService.sendTab('toggleInspector'); 29 | expect(app.visible).toBe(false); 30 | }); 31 | 32 | it('should toggle app by message, from invisible to visible', async () => { 33 | app.hide(); 34 | expect(app.visible).toBe(false); 35 | await messageService.sendTab('toggleInspector'); 36 | expect(app.visible).toBe(true); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /src/core/app-manager.ts: -------------------------------------------------------------------------------- 1 | import { Inspector } from 'colorins'; 2 | import { injectable } from 'inversify'; 3 | import 'reflect-metadata'; 4 | import { CapturedTab, MessageService } from '~/common'; 5 | import { App, Snackbar } from '~/elements'; 6 | 7 | @injectable() 8 | export class AppManager { 9 | constructor( 10 | private app: App, 11 | private inspector: Inspector, 12 | private snackbar: Snackbar, 13 | private messageService: MessageService, 14 | ) { 15 | this.app.hide(); 16 | this.handleViewportChange(); 17 | this.handleMessage(); 18 | this.handleColorCopy(); 19 | this.app.hide(); 20 | } 21 | 22 | private handleMessage() { 23 | this.messageService.on('toggleInspector', this.toggleInspector); 24 | } 25 | 26 | /** 27 | * Keep capturing current tab image when viewport changed. 28 | */ 29 | private handleViewportChange() { 30 | let timerId: number; 31 | const debounceSend = () => { 32 | if (!this.app.visible) { 33 | return; 34 | } 35 | window.clearTimeout(timerId); 36 | this.app.hide(); 37 | timerId = window.setTimeout(() => { 38 | this.requestCapture(); 39 | }, 200); 40 | }; 41 | window.addEventListener('scroll', debounceSend); 42 | window.addEventListener('resize', debounceSend); 43 | } 44 | 45 | private async requestCapture() { 46 | const detail = await this.messageService.send( 47 | 'requestCapture', 48 | ); 49 | this.updateImage(detail); 50 | } 51 | 52 | /** 53 | * Sync inspector's image with captured tab. 54 | */ 55 | private updateImage = (detail: CapturedTab) => { 56 | const { imgSrc, width, height } = detail; 57 | const img = new Image(width, height); 58 | img.src = imgSrc; 59 | this.inspector.loadImage(img); 60 | this.app.show(); 61 | }; 62 | 63 | private toggleInspector = () => { 64 | const nextValue = !this.app.visible; 65 | if (nextValue) { 66 | this.requestCapture(); 67 | this.app.show(); 68 | } else { 69 | this.app.hide(); 70 | } 71 | return nextValue; 72 | }; 73 | 74 | private handleColorCopy() { 75 | this.inspector.onCopy = (color) => { 76 | this.snackbar.notifyColorCopy(color); 77 | }; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from './app-manager'; 2 | -------------------------------------------------------------------------------- /src/core/store.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @deprecated 3 | */ 4 | import { createStore, combineReducers, Store, AnyAction } from 'redux'; 5 | export { Store } from 'redux'; 6 | export const APP_STORE = 'appStore'; 7 | 8 | export interface AppState { 9 | active: boolean; 10 | } 11 | 12 | const active$ = (state = false, action: AnyAction) => { 13 | switch (action.type) { 14 | case 'SET_ACTIVE': 15 | return action.value; 16 | default: 17 | return state; 18 | } 19 | }; 20 | 21 | export const store: Store = createStore( 22 | combineReducers({ 23 | active: active$, 24 | }) 25 | ); 26 | -------------------------------------------------------------------------------- /src/elements/app.ts: -------------------------------------------------------------------------------- 1 | import { 2 | LitElement, 3 | html, 4 | customElement, 5 | queryAsync, 6 | query, 7 | css, 8 | } from 'lit-element'; 9 | 10 | @customElement('ac-root') 11 | export class App extends LitElement { 12 | static styles = css` 13 | :host { 14 | display: block; 15 | width: 100%; 16 | height: 100%; 17 | position: fixed; 18 | top: 0; 19 | z-index: ${Number.MAX_SAFE_INTEGER}; 20 | left: 0; 21 | visibility: inherit; 22 | } 23 | `; 24 | 25 | public async injectCanvas(canvas: HTMLCanvasElement): Promise { 26 | const dom = await this.canvasContainer; 27 | dom.append(canvas); 28 | } 29 | 30 | @queryAsync('.canvas-container') 31 | public canvasContainer: Promise; 32 | 33 | @query('canvas') 34 | public canvas: HTMLCanvasElement; 35 | 36 | public get visible() { 37 | return this.style.visibility !== 'hidden'; 38 | } 39 | 40 | public hide() { 41 | this.style.visibility = 'hidden'; 42 | this.style.cursor = `inherit`; 43 | } 44 | 45 | public show() { 46 | this.style.visibility = 'inherit'; 47 | this.style.cursor = `none`; 48 | } 49 | 50 | render() { 51 | return html`
`; 52 | } 53 | } 54 | 55 | declare global { 56 | interface HTMLElementTagNameMap { 57 | 'ac-root': App; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/elements/color-spot.ts: -------------------------------------------------------------------------------- 1 | import { LitElement, html, customElement, property, css } from 'lit-element'; 2 | import { styleMap } from 'lit-html/directives/style-map'; 3 | 4 | @customElement('ac-color-spot') 5 | class ColorSpot extends LitElement { 6 | static styles = css` 7 | .spot { 8 | box-sizing: border-box; 9 | display: block; 10 | border-radius: 3px; 11 | width: 20px; 12 | height: 20px; 13 | margin-right: 6px; 14 | } 15 | `; 16 | 17 | @property() 18 | public color = '#000000'; 19 | 20 | private get spotStyles() { 21 | return styleMap({ 22 | backgroundColor: this.color, 23 | }); 24 | } 25 | 26 | render() { 27 | return html`
`; 28 | } 29 | } 30 | 31 | declare global { 32 | interface HTMLElementTagNameMap { 33 | 'ac-color-spot': ColorSpot; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/elements/index.ts: -------------------------------------------------------------------------------- 1 | export * from './app'; 2 | export * from './snackbar'; 3 | export * from './color-spot'; 4 | -------------------------------------------------------------------------------- /src/elements/snackbar.ts: -------------------------------------------------------------------------------- 1 | import { 2 | css, 3 | customElement, 4 | html, 5 | internalProperty, 6 | LitElement, 7 | } from 'lit-element'; 8 | import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'; 9 | import * as nearestColour from 'nearest-color'; 10 | 11 | const DURATION = 2000; 12 | 13 | const colours = { 14 | black: '#000', 15 | white: '#fff', 16 | slate: { 17 | 50: '#f8fafc', 18 | 100: '#f1f5f9', 19 | 200: '#e2e8f0', 20 | 300: '#cbd5e1', 21 | 400: '#94a3b8', 22 | 500: '#64748b', 23 | 600: '#475569', 24 | 700: '#334155', 25 | 800: '#1e293b', 26 | 900: '#0f172a', 27 | }, 28 | gray: { 29 | 50: '#f9fafb', 30 | 100: '#f3f4f6', 31 | 200: '#e5e7eb', 32 | 300: '#d1d5db', 33 | 400: '#9ca3af', 34 | 500: '#6b7280', 35 | 600: '#4b5563', 36 | 700: '#374151', 37 | 800: '#1f2937', 38 | 900: '#111827', 39 | }, 40 | zinc: { 41 | 50: '#fafafa', 42 | 100: '#f4f4f5', 43 | 200: '#e4e4e7', 44 | 300: '#d4d4d8', 45 | 400: '#a1a1aa', 46 | 500: '#71717a', 47 | 600: '#52525b', 48 | 700: '#3f3f46', 49 | 800: '#27272a', 50 | 900: '#18181b', 51 | }, 52 | neutral: { 53 | 50: '#fafafa', 54 | 100: '#f5f5f5', 55 | 200: '#e5e5e5', 56 | 300: '#d4d4d4', 57 | 400: '#a3a3a3', 58 | 500: '#737373', 59 | 600: '#525252', 60 | 700: '#404040', 61 | 800: '#262626', 62 | 900: '#171717', 63 | }, 64 | stone: { 65 | 50: '#fafaf9', 66 | 100: '#f5f5f4', 67 | 200: '#e7e5e4', 68 | 300: '#d6d3d1', 69 | 400: '#a8a29e', 70 | 500: '#78716c', 71 | 600: '#57534e', 72 | 700: '#44403c', 73 | 800: '#292524', 74 | 900: '#1c1917', 75 | }, 76 | red: { 77 | 50: '#fef2f2', 78 | 100: '#fee2e2', 79 | 200: '#fecaca', 80 | 300: '#fca5a5', 81 | 400: '#f87171', 82 | 500: '#ef4444', 83 | 600: '#dc2626', 84 | 700: '#b91c1c', 85 | 800: '#991b1b', 86 | 900: '#7f1d1d', 87 | }, 88 | orange: { 89 | 50: '#fff7ed', 90 | 100: '#ffedd5', 91 | 200: '#fed7aa', 92 | 300: '#fdba74', 93 | 400: '#fb923c', 94 | 500: '#f97316', 95 | 600: '#ea580c', 96 | 700: '#c2410c', 97 | 800: '#9a3412', 98 | 900: '#7c2d12', 99 | }, 100 | amber: { 101 | 50: '#fffbeb', 102 | 100: '#fef3c7', 103 | 200: '#fde68a', 104 | 300: '#fcd34d', 105 | 400: '#fbbf24', 106 | 500: '#f59e0b', 107 | 600: '#d97706', 108 | 700: '#b45309', 109 | 800: '#92400e', 110 | 900: '#78350f', 111 | }, 112 | yellow: { 113 | 50: '#fefce8', 114 | 100: '#fef9c3', 115 | 200: '#fef08a', 116 | 300: '#fde047', 117 | 400: '#facc15', 118 | 500: '#eab308', 119 | 600: '#ca8a04', 120 | 700: '#a16207', 121 | 800: '#854d0e', 122 | 900: '#713f12', 123 | }, 124 | lime: { 125 | 50: '#f7fee7', 126 | 100: '#ecfccb', 127 | 200: '#d9f99d', 128 | 300: '#bef264', 129 | 400: '#a3e635', 130 | 500: '#84cc16', 131 | 600: '#65a30d', 132 | 700: '#4d7c0f', 133 | 800: '#3f6212', 134 | 900: '#365314', 135 | }, 136 | green: { 137 | 50: '#f0fdf4', 138 | 100: '#dcfce7', 139 | 200: '#bbf7d0', 140 | 300: '#86efac', 141 | 400: '#4ade80', 142 | 500: '#22c55e', 143 | 600: '#16a34a', 144 | 700: '#15803d', 145 | 800: '#166534', 146 | 900: '#14532d', 147 | }, 148 | emerald: { 149 | 50: '#ecfdf5', 150 | 100: '#d1fae5', 151 | 200: '#a7f3d0', 152 | 300: '#6ee7b7', 153 | 400: '#34d399', 154 | 500: '#10b981', 155 | 600: '#059669', 156 | 700: '#047857', 157 | 800: '#065f46', 158 | 900: '#064e3b', 159 | }, 160 | teal: { 161 | 50: '#f0fdfa', 162 | 100: '#ccfbf1', 163 | 200: '#99f6e4', 164 | 300: '#5eead4', 165 | 400: '#2dd4bf', 166 | 500: '#14b8a6', 167 | 600: '#0d9488', 168 | 700: '#0f766e', 169 | 800: '#115e59', 170 | 900: '#134e4a', 171 | }, 172 | cyan: { 173 | 50: '#ecfeff', 174 | 100: '#cffafe', 175 | 200: '#a5f3fc', 176 | 300: '#67e8f9', 177 | 400: '#22d3ee', 178 | 500: '#06b6d4', 179 | 600: '#0891b2', 180 | 700: '#0e7490', 181 | 800: '#155e75', 182 | 900: '#164e63', 183 | }, 184 | sky: { 185 | 50: '#f0f9ff', 186 | 100: '#e0f2fe', 187 | 200: '#bae6fd', 188 | 300: '#7dd3fc', 189 | 400: '#38bdf8', 190 | 500: '#0ea5e9', 191 | 600: '#0284c7', 192 | 700: '#0369a1', 193 | 800: '#075985', 194 | 900: '#0c4a6e', 195 | }, 196 | blue: { 197 | 50: '#eff6ff', 198 | 100: '#dbeafe', 199 | 200: '#bfdbfe', 200 | 300: '#93c5fd', 201 | 400: '#60a5fa', 202 | 500: '#3b82f6', 203 | 600: '#2563eb', 204 | 700: '#1d4ed8', 205 | 800: '#1e40af', 206 | 900: '#1e3a8a', 207 | }, 208 | indigo: { 209 | 50: '#eef2ff', 210 | 100: '#e0e7ff', 211 | 200: '#c7d2fe', 212 | 300: '#a5b4fc', 213 | 400: '#818cf8', 214 | 500: '#6366f1', 215 | 600: '#4f46e5', 216 | 700: '#4338ca', 217 | 800: '#3730a3', 218 | 900: '#312e81', 219 | }, 220 | violet: { 221 | 50: '#f5f3ff', 222 | 100: '#ede9fe', 223 | 200: '#ddd6fe', 224 | 300: '#c4b5fd', 225 | 400: '#a78bfa', 226 | 500: '#8b5cf6', 227 | 600: '#7c3aed', 228 | 700: '#6d28d9', 229 | 800: '#5b21b6', 230 | 900: '#4c1d95', 231 | }, 232 | purple: { 233 | 50: '#faf5ff', 234 | 100: '#f3e8ff', 235 | 200: '#e9d5ff', 236 | 300: '#d8b4fe', 237 | 400: '#c084fc', 238 | 500: '#a855f7', 239 | 600: '#9333ea', 240 | 700: '#7e22ce', 241 | 800: '#6b21a8', 242 | 900: '#581c87', 243 | }, 244 | fuchsia: { 245 | 50: '#fdf4ff', 246 | 100: '#fae8ff', 247 | 200: '#f5d0fe', 248 | 300: '#f0abfc', 249 | 400: '#e879f9', 250 | 500: '#d946ef', 251 | 600: '#c026d3', 252 | 700: '#a21caf', 253 | 800: '#86198f', 254 | 900: '#701a75', 255 | }, 256 | pink: { 257 | 50: '#fdf2f8', 258 | 100: '#fce7f3', 259 | 200: '#fbcfe8', 260 | 300: '#f9a8d4', 261 | 400: '#f472b6', 262 | 500: '#ec4899', 263 | 600: '#db2777', 264 | 700: '#be185d', 265 | 800: '#9d174d', 266 | 900: '#831843', 267 | }, 268 | rose: { 269 | 50: '#fff1f2', 270 | 100: '#ffe4e6', 271 | 200: '#fecdd3', 272 | 300: '#fda4af', 273 | 400: '#fb7185', 274 | 500: '#f43f5e', 275 | 600: '#e11d48', 276 | 700: '#be123c', 277 | 800: '#9f1239', 278 | 900: '#881337', 279 | }, 280 | }; 281 | 282 | const tailwindColours = {}; 283 | 284 | for (const coloursKey in colours) { 285 | if (typeof colours[coloursKey] === 'string') { 286 | tailwindColours[coloursKey] = colours[coloursKey]; 287 | } else { 288 | for (const nestedKey in colours[coloursKey]) { 289 | tailwindColours[`${coloursKey}-${nestedKey}`] = 290 | colours[coloursKey][nestedKey]; 291 | } 292 | } 293 | } 294 | 295 | export const snackbarFactory = (wrapper: HTMLElement) => { 296 | const dom = document.createElement('ac-snackbar'); 297 | wrapper.shadowRoot.append(dom); 298 | return dom; 299 | }; 300 | 301 | @customElement('ac-snackbar') 302 | export class Snackbar extends LitElement { 303 | static styles = css` 304 | :host { 305 | position: fixed; 306 | top: 10px; 307 | right: 10px; 308 | background: #323232; 309 | padding: 6px 16px; 310 | border-radius: 4px; 311 | z-index: ${Number.MAX_SAFE_INTEGER}; 312 | box-sizing: border-box; 313 | height: 48px; 314 | color: white; 315 | opacity: 0; 316 | transition: opacity 0.15s; 317 | pointer-events: none; 318 | } 319 | 320 | :host(.visible) { 321 | opacity: 1; 322 | } 323 | 324 | .content { 325 | display: flex; 326 | align-items: center; 327 | height: 100%; 328 | } 329 | `; 330 | 331 | @internalProperty() 332 | private html = ''; 333 | 334 | private _timerId = null; 335 | 336 | public notifyColorCopy(color: string) { 337 | const getNearestTailwindColour = nearestColour.from(tailwindColours); 338 | const nearestTailwindColour = getNearestTailwindColour(color); 339 | this.openHtml(` 340 | 341 |
342 | ${nearestTailwindColour['name']} copied! 343 |
344 | `); 345 | } 346 | 347 | private openHtml(html: string) { 348 | window.clearTimeout(this._timerId); 349 | this.html = html; 350 | this.classList.add('visible'); 351 | this._timerId = window.setTimeout(() => { 352 | this.classList.remove('visible'); 353 | }, DURATION); 354 | } 355 | 356 | render() { 357 | return html`
${unsafeHTML(this.html)}
`; 358 | } 359 | } 360 | 361 | declare global { 362 | interface HTMLElementTagNameMap { 363 | 'ac-snackbar': Snackbar; 364 | } 365 | } 366 | -------------------------------------------------------------------------------- /src/hot-reload.ts: -------------------------------------------------------------------------------- 1 | import { toPromise } from '~/common'; 2 | 3 | /** 4 | * Recursively get all FileEntry and DirectoryEntry. 5 | */ 6 | async function getAllEntries(dir: DirectoryEntry) { 7 | const reader = dir.createReader(); 8 | const entries = await toPromise(reader.readEntries.bind(reader))(); 9 | const result = []; 10 | while (entries[0]) { 11 | const entry = entries.shift(); 12 | if (entry.isFile) { 13 | result.push(entry); 14 | } else { 15 | const subEntries = await getAllEntries(entry as DirectoryEntry); 16 | subEntries.forEach((e) => result.push(e)); 17 | } 18 | } 19 | return result; 20 | } 21 | 22 | async function watchChanges() { 23 | const dir = await toPromise( 24 | chrome.runtime.getPackageDirectoryEntry 25 | )(); 26 | const entries = await getAllEntries(dir); 27 | 28 | const modificationTimeMap: { [fullPath: string]: Date } = {}; 29 | await Promise.all( 30 | entries.map((entry) => 31 | toPromise(entry.getMetadata.bind(entry))().then( 32 | ({ modificationTime }) => { 33 | modificationTimeMap[entry.fullPath] = modificationTime; 34 | } 35 | ) 36 | ) 37 | ); 38 | 39 | window.setInterval(() => { 40 | entries.forEach(async (entry) => { 41 | const metadata = await toPromise( 42 | entry.getMetadata.bind(entry) 43 | )(); 44 | 45 | if ( 46 | modificationTimeMap[entry.fullPath].getTime() !== 47 | metadata.modificationTime.getTime() 48 | ) { 49 | chrome.runtime.reload(); 50 | } 51 | }); 52 | }, 1000); 53 | } 54 | 55 | chrome.management.getSelf((self) => { 56 | if (self.installType === 'development') { 57 | console.log(`start hot reload at ${new Date().toLocaleString()}`); 58 | watchChanges(); 59 | } 60 | }); 61 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Tailwind Color Picker", 3 | "short_name": "TailwindColorPicker", 4 | "version": "1.0.1", 5 | "manifest_version": 3, 6 | "description": "Tailwind Color Picker allows you to pick a pixel from any web page and return the closest tailwind color.", 7 | "homepage_url": "https://github.com/nutlope/tailwind-color-picker", 8 | "icons": { 9 | "16": "assets/icon16.png", 10 | "48": "assets/icon48.png", 11 | "128": "assets/icon128.png" 12 | }, 13 | "background": { 14 | "service_worker": "background.js" 15 | }, 16 | "action": { 17 | "default_title": "Click the icon", 18 | "name": "Click to invoke the inspector" 19 | }, 20 | "permissions": ["activeTab", "scripting"], 21 | "commands": { 22 | "toggle-inspector": { 23 | "suggested_key": { 24 | "windows": "Ctrl+Shift+X", 25 | "linux": "Ctrl+Shift+X", 26 | "mac": "Command+Shift+X", 27 | "chromeos": "Ctrl+Shift+X" 28 | }, 29 | "description": "Toggle the inspector" 30 | } 31 | }, 32 | "web_accessible_resources": [ 33 | { 34 | "resources": ["assets/*"], 35 | "matches": [""] 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /src/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/popup/color-context.ts: -------------------------------------------------------------------------------- 1 | import React, { useState, useContext } from 'react'; 2 | import { ChromaColor } from './models'; 3 | 4 | const kDefaultColor = ChromaColor.fromHSV(0, 1, 1); 5 | 6 | export const ColorContext = React.createContext({ 7 | color: kDefaultColor, 8 | setColor: null, 9 | }); 10 | 11 | export function useColorContextDefault() { 12 | const [color, setColor] = useState(kDefaultColor); 13 | return { color, setColor }; 14 | } 15 | 16 | export function useColorContext() { 17 | return useContext(ColorContext); 18 | } 19 | -------------------------------------------------------------------------------- /src/popup/components/alpha-slider.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { useColorContext } from '../color-context'; 4 | import { kSliderHeight, kAlphaGridCss, kSliderThumbSize } from '../constants'; 5 | import { StyledSlider } from './styled-slider'; 6 | 7 | const Wrapper = styled.div` 8 | height: ${kSliderHeight}px; 9 | `; 10 | 11 | export function AlphaSlider() { 12 | const { color, setColor } = useColorContext(); 13 | const updateColor = (event: React.FormEvent) => { 14 | setColor( 15 | color.clone({ 16 | a: parseFloat((event.target as HTMLInputElement).value), 17 | }) 18 | ); 19 | }; 20 | return ( 21 | 22 | 31 | 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/popup/components/app.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { useColorContextDefault, ColorContext } from '../color-context'; 4 | import { kMainWidth } from '../constants'; 5 | import { AlphaSlider } from './alpha-slider'; 6 | import { CirclePicker } from './circle-picker'; 7 | import { Dropper } from './dropper'; 8 | import { HueSlider } from './hue-slider'; 9 | import { SaturationCanvas } from './saturation-canvas'; 10 | import { ValuePicker } from './value-picker'; 11 | 12 | const Wrapper = styled.div` 13 | display: flex; 14 | flex-direction: column; 15 | width: ${kMainWidth}px; 16 | box-shadow: rgba(0, 0, 0, 0.37) 0px 1px 4px 0px; 17 | padding-bottom: 8px; 18 | `; 19 | 20 | const ControlSection = styled.div` 21 | display: flex; 22 | align-items: center; 23 | margin: 14px 14px 0; 24 | `; 25 | 26 | const SliderBlock = styled.div` 27 | flex: 1; 28 | align-self: stretch; 29 | margin-left: 14px; 30 | display: flex; 31 | flex-direction: column; 32 | justify-content: space-between; 33 | `; 34 | 35 | export function App() { 36 | return ( 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /src/popup/components/circle-picker.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { ColorContext } from '../color-context'; 4 | import { kCirclePickerSize, kAlphaGridCss } from '../constants'; 5 | import { ChromaColor } from '../models'; 6 | 7 | interface WrapperProps { 8 | color: ChromaColor; 9 | } 10 | 11 | const Wrapper = styled.div.attrs((props: WrapperProps) => ({ 12 | style: { 13 | background: props.color.css(), 14 | }, 15 | }))` 16 | width: ${kCirclePickerSize}px; 17 | height: ${kCirclePickerSize}px; 18 | border-radius: 50%; 19 | position: relative; 20 | 21 | &::before { 22 | content: '\\00a0'; 23 | display: block; 24 | width: 100%; 25 | height: 100%; 26 | position: absolute; 27 | z-index: -1; 28 | border-radius: 50%; 29 | background: ${kAlphaGridCss}; 30 | } 31 | `; 32 | 33 | export class CirclePicker extends React.Component { 34 | static contextType = ColorContext; 35 | 36 | render() { 37 | return ; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/popup/components/dropper.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, unmountComponentAtNode } from 'react-dom'; 3 | import { act } from 'react-dom/test-utils'; 4 | import { Dropper } from './dropper'; 5 | 6 | describe('Dropper', () => { 7 | let container = null; 8 | beforeEach(() => { 9 | // setup a DOM element as a render target 10 | container = document.createElement('div'); 11 | document.body.appendChild(container); 12 | }); 13 | 14 | afterEach(() => { 15 | // cleanup on exiting 16 | unmountComponentAtNode(container); 17 | container.remove(); 18 | container = null; 19 | }); 20 | 21 | it('should render', () => { 22 | act(() => { 23 | render(, container); 24 | }); 25 | expect(true).toBeTruthy(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/popup/components/dropper.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { kDropperColor, kActiveColor } from '../constants'; 4 | import { lazyInject, MessageService } from '~/common'; 5 | 6 | interface WrapperProps { 7 | active: boolean; 8 | } 9 | 10 | const Wrapper = styled.div` 11 | width: 16px; 12 | height: 16px; 13 | margin-right: 14px; 14 | color: ${(props) => (props.active ? kActiveColor : kDropperColor)}; 15 | `; 16 | 17 | interface State { 18 | active: boolean; 19 | } 20 | 21 | export class Dropper extends React.Component<{}, State> { 22 | @lazyInject(MessageService) 23 | private messageService: MessageService; 24 | 25 | constructor(props: {}) { 26 | super(props); 27 | this.state = { 28 | active: false, 29 | }; 30 | // Note: only invoke `setState` here to ensure single source of truth on content script. 31 | this.messageService.sendTab('requestDropperState').then((state) => { 32 | this.setState(state); 33 | }); 34 | } 35 | 36 | private toggleActive = async () => { 37 | await this.messageService.sendTab('toggleInspector'); 38 | window.close(); 39 | }; 40 | 41 | render() { 42 | return ( 43 | 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/popup/components/hue-slider.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { useColorContext } from '../color-context'; 4 | import { kSliderThumbSize, kSliderHeight } from '../constants'; 5 | import { StyledSlider } from './styled-slider'; 6 | 7 | const Wrapper = styled.div` 8 | height: ${kSliderHeight}px; 9 | `; 10 | 11 | const hueGradientCss = `linear-gradient( 12 | to right, 13 | rgb(255, 0, 0) 0%, 14 | rgb(255, 0, 255) 17%, 15 | rgb(0, 0, 255) 33%, 16 | rgb(0, 255, 255) 50%, 17 | rgb(0, 255, 0) 67%, 18 | rgb(255, 255, 0) 83%, 19 | rgb(255, 0, 0) 100% 20 | )`; 21 | 22 | export function HueSlider() { 23 | const { color, setColor } = useColorContext(); 24 | const updateColor = (event: React.FormEvent) => { 25 | const hue = 360 - parseFloat((event.target as HTMLInputElement).value); 26 | setColor( 27 | color.clone({ 28 | h: hue, 29 | }) 30 | ); 31 | }; 32 | return ( 33 | 34 | 42 | 43 | ); 44 | } 45 | -------------------------------------------------------------------------------- /src/popup/components/saturation-canvas.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, unmountComponentAtNode } from 'react-dom'; 3 | import { act } from 'react-dom/test-utils'; 4 | import { SaturationCanvas } from './saturation-canvas'; 5 | 6 | describe('SaturationCanvas', () => { 7 | let container = null; 8 | beforeEach(() => { 9 | // setup a DOM element as a render target 10 | container = document.createElement('div'); 11 | document.body.appendChild(container); 12 | }); 13 | 14 | afterEach(() => { 15 | // cleanup on exiting 16 | unmountComponentAtNode(container); 17 | container.remove(); 18 | container = null; 19 | }); 20 | 21 | it('should render', () => { 22 | act(() => { 23 | render(, container); 24 | }); 25 | expect(true).toBeTruthy(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /src/popup/components/saturation-canvas.tsx: -------------------------------------------------------------------------------- 1 | import paper from 'paper'; 2 | import React from 'react'; 3 | import styled from 'styled-components'; 4 | import { ColorContext } from '../color-context'; 5 | import { kSaturationCanvasHeight } from '../constants'; 6 | import { ChromaColor } from '../models'; 7 | 8 | interface WrapperProps { 9 | color: ChromaColor; 10 | } 11 | 12 | const Wrapper = styled.canvas.attrs((props: WrapperProps) => ({ 13 | style: { 14 | background: `linear-gradient(to top, #000, rgba(0, 0, 0, 0)), 15 | linear-gradient(to right, #fff, rgba(255, 255, 255, 0)), 16 | ${props.color.hueCss()}`, 17 | }, 18 | }))` 19 | height: ${kSaturationCanvasHeight}px; 20 | `; 21 | 22 | export class SaturationCanvas extends React.Component { 23 | static contextType = ColorContext; 24 | private project: paper.Project; 25 | private pointer: paper.Path; 26 | private width: number; 27 | private height: number; 28 | 29 | // Somehow context.color is different in setColor and componentDidUpdate, 30 | // hence we use this flag to skip pointer update in componentDidUpdate. 31 | private internalUpdating = false; 32 | 33 | private initCanvas = (element: HTMLCanvasElement) => { 34 | this.project = new paper.Project(element); 35 | 36 | const { width, height } = this.project.view.viewSize; 37 | this.width = width; 38 | this.height = height; 39 | 40 | // located at top-right corner 41 | this.pointer = new paper.Path.Circle({ 42 | center: [this.width, 0], 43 | radius: 6, 44 | strokeColor: 'white', 45 | }); 46 | 47 | this.project.view.onMouseDrag = this.updateColor; 48 | this.project.view.onMouseDown = this.updateColor; 49 | }; 50 | 51 | private updateColor = (event: paper.MouseEvent) => { 52 | // update pointer position first 53 | const { x, y } = event.point; 54 | const px = Math.max(0, Math.min(x, this.width)); 55 | const py = Math.max(0, Math.min(y, this.height)); 56 | this.pointer.position = new paper.Point(px, py); 57 | 58 | this.internalUpdating = true; 59 | this.context.setColor(this.pointToColor(this.pointer.position)); 60 | this.internalUpdating = false; 61 | }; 62 | 63 | private pointToColor(point: paper.Point): ChromaColor { 64 | const { x, y } = point; 65 | return this.context.color.clone({ 66 | s: x / this.width, 67 | v: 1 - y / this.height, 68 | }); 69 | } 70 | 71 | private colorToPoint(color: ChromaColor): paper.Point { 72 | const { s, v } = color.hsv; 73 | return new paper.Point(s * this.width, (1 - v) * this.height); 74 | } 75 | 76 | componentDidUpdate() { 77 | if (this.internalUpdating) { 78 | return; 79 | } 80 | this.pointer.position = this.colorToPoint(this.context.color); 81 | } 82 | 83 | render() { 84 | return ( 85 | 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/popup/components/styled-slider.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | interface StyledSliderProps { 5 | max?: number; 6 | min?: number; 7 | defaultValue?: number; 8 | value?: number; 9 | onChange?: (event: React.FormEvent) => void; 10 | primaryBackground?: string; 11 | secondaryBackground?: string; 12 | thumbSize?: number; 13 | } 14 | 15 | const defaultProps = { 16 | primaryBackground: 'white', 17 | secondaryBackground: 'white', 18 | thumbSize: 10, 19 | }; 20 | 21 | const Wrapper = styled.div` 22 | width: 100%; 23 | height: 100%; 24 | border-width: 0; 25 | border-radius: 2px; 26 | background-position: center; 27 | background: ${(props) => props.secondaryBackground}; 28 | `; 29 | 30 | const Slider = styled.input.attrs((props: StyledSliderProps) => { 31 | return { 32 | style: { 33 | background: props.primaryBackground, 34 | }, 35 | }; 36 | })` 37 | appearance: none; 38 | outline: none; 39 | width: 100%; 40 | height: 100%; 41 | border-width: 0; 42 | border-radius: 2px; 43 | cursor: pointer; 44 | display: block; 45 | margin: 0; 46 | 47 | &::-webkit-slider-thumb { 48 | appearance: none; 49 | width: ${(props) => props.thumbSize}px; 50 | height: ${(props) => props.thumbSize}px; 51 | background: white; 52 | border-radius: 50%; 53 | box-shadow: rgba(0, 0, 0, 0.37) 0px 1px 4px 0px; 54 | } 55 | 56 | &::-webkit-slider-runnable-track { 57 | margin: -${(props) => props.thumbSize / 2}px; 58 | } 59 | `; 60 | 61 | export function StyledSlider(propsIn: StyledSliderProps) { 62 | const props = { ...defaultProps, ...propsIn }; 63 | return ( 64 | 65 | 66 | 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /src/popup/components/value-picker/hex-input.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { LabeledInput } from './labeled-input'; 3 | import { ColorContext } from '~popup/color-context'; 4 | import { ChromaColor } from '~popup/models'; 5 | 6 | interface State { 7 | selected: boolean; 8 | } 9 | 10 | export class HEXInput extends React.Component<{}, State> { 11 | static contextType = ColorContext; 12 | 13 | constructor(props: {}) { 14 | super(props); 15 | this.state = { 16 | selected: false, 17 | }; 18 | } 19 | 20 | /** 21 | * Update the Input value but may not update the context color. 22 | */ 23 | private updateHEX = (hex: string) => { 24 | const { setColor } = this.context; 25 | const color = ChromaColor.create(hex); 26 | color && setColor(color); 27 | this.setState({ 28 | selected: false, 29 | }); 30 | }; 31 | 32 | private doMath = (hex: string, delta: number) => { 33 | const num = parseInt(hex.replace('#', ''), 16); 34 | if (isNaN(num)) { 35 | return; 36 | } 37 | 38 | // safely fill zero from left 39 | const newNum = (num + delta + 0x1000000).toString(16).substr(1); 40 | this.updateHEX(`#${newNum}`); 41 | this.setState({ 42 | selected: true, 43 | }); 44 | }; 45 | 46 | render() { 47 | const hex = this.context.color.hex; 48 | 49 | return ( 50 | this.doMath(hex, 1)} 56 | onArrowDown={(hex) => this.doMath(hex, -1)} 57 | selected={this.state.selected} 58 | /> 59 | ); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/popup/components/value-picker/index.ts: -------------------------------------------------------------------------------- 1 | export * from './value-picker'; 2 | -------------------------------------------------------------------------------- /src/popup/components/value-picker/labeled-input.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { 4 | kActiveColor, 5 | kInputBorderColor, 6 | kInputLabelColor, 7 | } from '~popup/constants'; 8 | 9 | const Wrapper = styled.div` 10 | display: flex; 11 | flex-direction: column; 12 | text-align: center; 13 | flex: 1; 14 | margin-right: 8px; 15 | 16 | & input { 17 | text-align: center; 18 | outline: none; 19 | padding: 2px 0; 20 | margin-bottom: 4px; 21 | font-family: Menlo; 22 | width: 100%; 23 | border: solid 1px ${kInputBorderColor}; 24 | } 25 | 26 | & input:focus { 27 | border: solid 1px ${kActiveColor}; 28 | } 29 | 30 | & span { 31 | color: ${kInputLabelColor}; 32 | } 33 | `; 34 | 35 | export interface Props { 36 | label?: string; 37 | defaultValue?: string; 38 | value?: string; 39 | maxLength?: number; 40 | onChange?: (value: string) => void; 41 | onArrowUp?: (value: string) => void; 42 | onArrowDown?: (value: string) => void; 43 | selected?: boolean; 44 | } 45 | 46 | interface State { 47 | // To make user be able to freely input something 48 | transientValue: string; 49 | } 50 | 51 | /** 52 | * @remarks 53 | * The internal element is not only tracking the Props.value, 54 | * but also the internal state `transientValue`. 55 | */ 56 | export class LabeledInput extends React.Component { 57 | private inputRef: HTMLInputElement; 58 | 59 | constructor(props: Props) { 60 | super(props); 61 | this.state = { 62 | transientValue: props.value, 63 | }; 64 | } 65 | 66 | shouldComponentUpdate(nextProps: Props, nextState: State) { 67 | // change externally, bypass the changing to internal 68 | if (this.props.value !== nextProps.value) { 69 | this.setState({ 70 | transientValue: nextProps.value, 71 | }); 72 | } else if ( 73 | this.state.transientValue !== nextState.transientValue && 74 | nextState.transientValue !== this.props.value && 75 | this.props.onChange 76 | ) { 77 | // change internally(explicitly by user input), emit onChange event 78 | this.props.onChange(nextState.transientValue); 79 | } 80 | return true; 81 | } 82 | 83 | componentDidUpdate() { 84 | if (this.props.selected) { 85 | this.inputRef.select(); 86 | } 87 | } 88 | 89 | /** 90 | * Update internal state. 91 | */ 92 | updateTransientValue = (event: React.FormEvent) => { 93 | const value = (event.target as HTMLInputElement).value; 94 | this.setState({ 95 | transientValue: value, 96 | }); 97 | }; 98 | 99 | emitArrowEvent = (event: React.KeyboardEvent) => { 100 | const action = { 101 | // down arrow key 102 | 40: this.props.onArrowDown, 103 | // up arrow key 104 | 38: this.props.onArrowUp, 105 | }[event.keyCode]; 106 | 107 | if (action) { 108 | action(this.state.transientValue); 109 | event.stopPropagation(); 110 | event.preventDefault(); 111 | } 112 | }; 113 | 114 | render() { 115 | const { maxLength } = this.props; 116 | const inputProps = { maxLength }; 117 | return ( 118 | 119 | (this.inputRef = ref)} 121 | value={this.state.transientValue} 122 | onChange={this.updateTransientValue} 123 | onKeyDown={this.emitArrowEvent} 124 | {...inputProps} 125 | /> 126 | {this.props.label} 127 | 128 | ); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/popup/components/value-picker/rgba-input.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { LabeledInput, Props as LabeledInputProps } from './labeled-input'; 3 | import { ColorContext } from '~popup/color-context'; 4 | 5 | type RGBAKey = 'r' | 'g' | 'b' | 'a'; 6 | 7 | interface State { 8 | selectedOn: RGBAKey; 9 | } 10 | 11 | interface InputPropsFactoryPayload { 12 | rgbaKey: RGBAKey; 13 | mathUnit: number; 14 | maxLength: number; 15 | } 16 | 17 | export class RGBAInput extends React.Component<{}, State> { 18 | static contextType = ColorContext; 19 | 20 | constructor(props: {}) { 21 | super(props); 22 | this.state = { 23 | selectedOn: null, 24 | }; 25 | } 26 | 27 | private updateColor = (rgbaKey: RGBAKey, value: string) => { 28 | const { color, setColor } = this.context; 29 | const num = parseFloat(value); 30 | if (isNaN(num)) { 31 | return; 32 | } 33 | setColor(color.cloneRGB({ [rgbaKey]: num })); 34 | this.setState({ 35 | selectedOn: null, 36 | }); 37 | }; 38 | 39 | private doMath = (rgbaKey: RGBAKey, value: string, delta: number) => { 40 | const num = parseFloat(value); 41 | if (isNaN(num)) { 42 | return; 43 | } 44 | this.updateColor(rgbaKey, (num + delta).toString()); 45 | this.setState({ 46 | selectedOn: rgbaKey, 47 | }); 48 | }; 49 | 50 | private inputPropsFactory = ( 51 | payload: InputPropsFactoryPayload 52 | ): Partial => { 53 | const { rgbaKey, mathUnit, maxLength } = payload; 54 | const { color } = this.context; 55 | const value = (rgbaKey === 'a' 56 | ? color.alpha 57 | : color.rgb[rgbaKey] 58 | ).toString(); 59 | 60 | const isSelected = (rgbaKey: RGBAKey) => { 61 | return this.state.selectedOn === rgbaKey; 62 | }; 63 | return { 64 | maxLength, 65 | label: rgbaKey.toUpperCase(), 66 | onChange: (value) => this.updateColor(rgbaKey, value), 67 | onArrowUp: (value) => this.doMath(rgbaKey, value, mathUnit), 68 | onArrowDown: (value) => this.doMath(rgbaKey, value, -mathUnit), 69 | selected: isSelected(rgbaKey), 70 | value, 71 | }; 72 | }; 73 | 74 | render() { 75 | return ( 76 | <> 77 | 84 | 91 | 98 | 105 | 106 | ); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/popup/components/value-picker/value-picker.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import styled from 'styled-components'; 3 | import { HEXInput } from './hex-input'; 4 | import { RGBAInput } from './rgba-input'; 5 | import { ColorContext } from '~popup/color-context'; 6 | import { kUpDownArrowSize, kUpDownArrowCss } from '~popup/constants'; 7 | 8 | const Wrapper = styled.div` 9 | display: flex; 10 | align-items: center; 11 | justify-content: space-between; 12 | width: 100%; 13 | font-family: Menlo; 14 | `; 15 | 16 | const UpDownArrow = styled.div` 17 | background: ${kUpDownArrowCss}; 18 | border-radius: 2px; 19 | width: ${kUpDownArrowSize}px; 20 | height: ${kUpDownArrowSize}px; 21 | background-size: contain; 22 | 23 | &:hover { 24 | background: ${kUpDownArrowCss}, #eeeeee; 25 | background-size: contain; 26 | } 27 | `; 28 | 29 | interface ValuePickerState { 30 | pickerIndex: number; 31 | } 32 | 33 | const pickers = [, ]; 34 | 35 | export class ValuePicker extends React.Component<{}, ValuePickerState> { 36 | static contextType = ColorContext; 37 | 38 | constructor(props: null) { 39 | super(props); 40 | this.state = { 41 | pickerIndex: 0, 42 | }; 43 | } 44 | 45 | rotatePicker = () => { 46 | this.setState({ 47 | pickerIndex: (this.state.pickerIndex + 1) % 2, 48 | }); 49 | }; 50 | 51 | render() { 52 | return ( 53 | 54 | {pickers[this.state.pickerIndex]} 55 | 56 | 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/popup/constants.ts: -------------------------------------------------------------------------------- 1 | export const kMainWidth = 232; 2 | export const kSaturationCanvasHeight = 124; 3 | export const kSliderHeight = 12; 4 | export const kSliderThumbSize = 13; 5 | export const kCirclePickerSize = 32; 6 | export const kAlphaGridCss = 7 | 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAALUlEQVQokWM8c+bMfwYswNjYGJswAxNWUTxgOGhg/P//P9ZQOnv2LHVsGA4aADluCnZeMIMKAAAAAElFTkSuQmCC")'; 8 | export const kActiveColor = '#2376e5'; 9 | 10 | export const kDropperColor = '#6e6e6e'; 11 | 12 | export const kInputBorderColor = '#e0e0e0'; 13 | export const kInputLabelColor = '#969696'; 14 | 15 | export const kUpDownArrowSize = 20; 16 | export const kUpDownArrowCss = 17 | 'url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDAgNzkuMTYwNDUxLCAyMDE3LzA1LzA2LTAxOjA4OjIxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+LUNEtwAAAL5JREFUSIntlsENwyAMRU0HMIvAQLAC65CBPIlH+T2BGlVUThTaKuJJPkSA38Fgh2ixmISzbAKw+962DUREpZTdeedM6ewA6CEi8N7Dew8Rweva5bTEqooYI4gIRIQYI1QV08UppS5tkXOeK661vklb1FoxRdzqOhK3eh/JeepWD5MduNUP886LWeL7i02ICJh5+JyY+fBzMvGzBvKpZaaU5vdqVUUIoUtDCN8ZEm0sMnOv69mx+N8/AovFwsITnGDfh3yHuUkAAAAASUVORK5CYII=")'; 18 | -------------------------------------------------------------------------------- /src/popup/fonts/icomoon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/popup/fonts/icomoon.eot -------------------------------------------------------------------------------- /src/popup/fonts/icomoon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/popup/fonts/icomoon.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/popup/fonts/icomoon.ttf -------------------------------------------------------------------------------- /src/popup/fonts/icomoon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nutlope/tailwind-color-picker/2158bbcaf9c6dbecd1649604ccf689a350688483/src/popup/fonts/icomoon.woff -------------------------------------------------------------------------------- /src/popup/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { App } from './components/app'; 4 | import 'regenerator-runtime/runtime'; 5 | 6 | ReactDOM.render(, document.getElementById('root')); 7 | -------------------------------------------------------------------------------- /src/popup/models/chroma-color.ts: -------------------------------------------------------------------------------- 1 | import chroma from 'chroma-js'; 2 | 3 | interface ColorChannel { 4 | h?: number; 5 | s?: number; 6 | v?: number; 7 | r?: number; 8 | g?: number; 9 | b?: number; 10 | a?: number; 11 | } 12 | 13 | export class ChromaColor { 14 | public static create(colorString: string) { 15 | const chromaColor = chroma(colorString); 16 | return new ChromaColor(chromaColor); 17 | } 18 | 19 | public static fromHSV(h: number, s: number, v: number) { 20 | const chromaColor = chroma(h, s, v, 'hsv'); 21 | return new ChromaColor(chromaColor); 22 | } 23 | 24 | public static fromRGB(r: number, g: number, b: number) { 25 | const chromaColor = chroma(r, g, b, 'rgb'); 26 | return new ChromaColor(chromaColor); 27 | } 28 | 29 | constructor(private color: chroma.Color) {} 30 | 31 | public get hsv(): ColorChannel { 32 | const [h, s, v] = this.color.hsv(); 33 | return { 34 | h: isNaN(h) ? 0 : h, 35 | s, 36 | v, 37 | }; 38 | } 39 | 40 | public get rgb(): ColorChannel { 41 | const [r, g, b] = this.color.rgb(); 42 | return { 43 | r, 44 | g, 45 | b, 46 | }; 47 | } 48 | 49 | public get hex(): string { 50 | return this.color.hex(); 51 | } 52 | 53 | public get alpha(): number { 54 | return this.color.alpha(); 55 | } 56 | 57 | public set alpha(a: number) { 58 | this.color = this.color.alpha(a); 59 | } 60 | 61 | public clone(payload: ColorChannel = {}): ChromaColor { 62 | const hsv = this.hsv; 63 | const { h = hsv.h, s = hsv.s, v = hsv.v, a = this.alpha } = payload; 64 | const chromaColor = ChromaColor.fromHSV(h, s, v); 65 | chromaColor.alpha = a; 66 | return chromaColor; 67 | } 68 | 69 | public cloneRGB({ 70 | r = this.rgb.r, 71 | g = this.rgb.g, 72 | b = this.rgb.b, 73 | a = this.alpha, 74 | }: ColorChannel = {}): ChromaColor { 75 | const chromaColor = ChromaColor.fromRGB(r, g, b); 76 | chromaColor.alpha = a; 77 | return chromaColor; 78 | } 79 | 80 | public css(): string { 81 | // Note: chroma.js's bug: the css() function actually changes the color instance itself 82 | return this.color.alpha(this.alpha).css(); 83 | } 84 | 85 | public hueCss(): string { 86 | return chroma.hsv(this.hsv.h, 1, 1).css(); 87 | } 88 | 89 | public rgbCss(): string { 90 | return this.color.alpha(1).css(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/popup/models/hsv-color.test.ts: -------------------------------------------------------------------------------- 1 | import { HSVColor } from './hsv-color'; 2 | 3 | describe('HSVColor', () => { 4 | it('should create', () => { 5 | const color = HSVColor.create(0, 1, 1); 6 | expect(color).toBeTruthy(); 7 | }); 8 | 9 | it('should get hue css', () => { 10 | const color = HSVColor.create(23, 0.3, 0.1); 11 | const hueColor = HSVColor.create(23, 1, 1); 12 | expect(color.hueCss()).toEqual(hueColor.css()); 13 | }); 14 | 15 | it('should clone', () => { 16 | const color = HSVColor.create(23, 0.3, 0.1); 17 | const cloned = color.clone(); 18 | expect(cloned.css()).toEqual(color.css()); 19 | expect(cloned).not.toBe(color); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/popup/models/hsv-color.ts: -------------------------------------------------------------------------------- 1 | import chroma from 'chroma-js'; 2 | 3 | interface ColorChannel { 4 | h?: number; 5 | s?: number; 6 | v?: number; 7 | r?: number; 8 | g?: number; 9 | b?: number; 10 | a?: number; 11 | } 12 | 13 | export class HSVColor { 14 | public static create(h: number, s: number, v: number, a = 1) { 15 | return new HSVColor(h, s, v, a); 16 | } 17 | 18 | public static fromHEX(hex: string) { 19 | if (!chroma.valid(hex)) { 20 | console.warn('Invalid hex:', hex); 21 | return; 22 | } 23 | let alpha = parseInt(hex.substr(7, 2), 16) / 255; 24 | alpha = isNaN(alpha) ? 1 : alpha; 25 | 26 | const chromaColor = chroma(hex); 27 | const [h, s, v] = chromaColor.hsv(); 28 | const color = new HSVColor(h, s, v, alpha); 29 | return color; 30 | } 31 | 32 | private h: number; 33 | private s: number; 34 | private v: number; 35 | private a = 1; 36 | private color: chroma.Color; 37 | 38 | constructor(h: number, s: number, v: number, a: number) { 39 | this.h = h; 40 | this.s = s; 41 | this.v = v; 42 | this.a = a; 43 | this.color = chroma.hsv(h, s, v).alpha(a); 44 | } 45 | 46 | public get hsv(): ColorChannel { 47 | return { 48 | h: this.h, 49 | s: this.s, 50 | v: this.v, 51 | }; 52 | } 53 | 54 | public get rgb(): ColorChannel { 55 | const [r, g, b] = this.color.rgb(); 56 | return { 57 | r, 58 | g, 59 | b, 60 | }; 61 | } 62 | 63 | public get hex(): string { 64 | return this.color.hex(); 65 | } 66 | 67 | public get alpha(): number { 68 | return this.a; 69 | } 70 | 71 | public clone({ 72 | h = this.h, 73 | s = this.s, 74 | v = this.v, 75 | a = this.a, 76 | }: ColorChannel = {}): HSVColor { 77 | return HSVColor.create(h, s, v, a); 78 | } 79 | 80 | public cloneRGB({ 81 | r = this.rgb.r, 82 | g = this.rgb.g, 83 | b = this.rgb.b, 84 | a = this.a, 85 | }: ColorChannel = {}): HSVColor { 86 | const [h, s, v] = chroma(r, g, b).alpha(a).hsv(); 87 | // h would be NaN for white, black and gray. 88 | return HSVColor.create(h || this.h, s, v, a); 89 | } 90 | 91 | public css(): string { 92 | return this.color.css(); 93 | } 94 | 95 | public hueCss(): string { 96 | return chroma.hsv(this.h, 1, 1).css(); 97 | } 98 | 99 | public rgbCss(): string { 100 | return this.color.alpha(1).css(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/popup/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './chroma-color'; 2 | -------------------------------------------------------------------------------- /src/popup/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'icomoon'; 3 | src: url('fonts/icomoon.eot?9a1056'); 4 | src: url('fonts/icomoon.eot?9a1056#iefix') format('embedded-opentype'), 5 | url('fonts/icomoon.ttf?9a1056') format('truetype'), 6 | url('fonts/icomoon.woff?9a1056') format('woff'), 7 | url('fonts/icomoon.svg?9a1056#icomoon') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | font-display: block; 11 | } 12 | 13 | [class^='icon-'], 14 | [class*=' icon-'] { 15 | /* use !important to prevent issues with browser extensions that change fonts */ 16 | font-family: 'icomoon' !important; 17 | speak: none; 18 | font-style: normal; 19 | font-weight: normal; 20 | font-variant: normal; 21 | text-transform: none; 22 | line-height: 1; 23 | 24 | /* Better Font Rendering =========== */ 25 | -webkit-font-smoothing: antialiased; 26 | -moz-osx-font-smoothing: grayscale; 27 | } 28 | 29 | .icon-dropper:before { 30 | content: '\e900'; 31 | } 32 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "jsx": "react", 5 | "noEmit": true, 6 | "esModuleInterop": true, 7 | "experimentalDecorators": true, 8 | "emitDecoratorMetadata": true, 9 | "allowSyntheticDefaultImports": true, 10 | "allowJs": true, 11 | "checkJs": true, 12 | "module": "commonjs", 13 | "moduleResolution": "node", 14 | "target": "es2015", 15 | "lib": ["dom", "es2015", "es5", "es6"], 16 | "noImplicitAny": false, 17 | "skipLibCheck": true, 18 | "paths": { 19 | "~*": ["./src/*"], 20 | "popup/*": ["./src/popup/*"] 21 | } 22 | }, 23 | "include": ["src/**/*"], 24 | "exclude": ["node_modules"] 25 | } 26 | --------------------------------------------------------------------------------