diff --git a/.prettierignore b/.prettierignore index ed879107992e..f302899cc8f1 100644 --- a/.prettierignore +++ b/.prettierignore @@ -27,6 +27,9 @@ packages/components/css packages/components/scss packages/components/docs/js +# Sketch +**/*.sketchplugin/** + # Changelogs **/CHANGELOG.md diff --git a/.yarn-offline-mirror/@babel-polyfill-7.4.4.tgz b/.yarn-offline-mirror/@babel-polyfill-7.4.4.tgz new file mode 100644 index 000000000000..f73d3a606c4b Binary files /dev/null and b/.yarn-offline-mirror/@babel-polyfill-7.4.4.tgz differ diff --git a/.yarn-offline-mirror/@skpm-babel-preset-0.2.1.tgz b/.yarn-offline-mirror/@skpm-babel-preset-0.2.1.tgz new file mode 100644 index 000000000000..72d0f85db44a Binary files /dev/null and b/.yarn-offline-mirror/@skpm-babel-preset-0.2.1.tgz differ diff --git a/.yarn-offline-mirror/@skpm-builder-0.7.0.tgz b/.yarn-offline-mirror/@skpm-builder-0.7.0.tgz new file mode 100644 index 000000000000..173e010a991d Binary files /dev/null and b/.yarn-offline-mirror/@skpm-builder-0.7.0.tgz differ diff --git a/.yarn-offline-mirror/@skpm-file-loader-2.0.1.tgz b/.yarn-offline-mirror/@skpm-file-loader-2.0.1.tgz new file mode 100644 index 000000000000..c6f314ad9f53 Binary files /dev/null and b/.yarn-offline-mirror/@skpm-file-loader-2.0.1.tgz differ diff --git a/.yarn-offline-mirror/@skpm-internal-utils-0.1.14.tgz b/.yarn-offline-mirror/@skpm-internal-utils-0.1.14.tgz new file mode 100644 index 000000000000..c4bbe1de4175 Binary files /dev/null and b/.yarn-offline-mirror/@skpm-internal-utils-0.1.14.tgz differ diff --git a/.yarn-offline-mirror/@skpm-nib-loader-0.1.1.tgz b/.yarn-offline-mirror/@skpm-nib-loader-0.1.1.tgz new file mode 100644 index 000000000000..67e2b4463334 Binary files /dev/null and b/.yarn-offline-mirror/@skpm-nib-loader-0.1.1.tgz differ diff --git a/.yarn-offline-mirror/author-regex-1.0.0.tgz b/.yarn-offline-mirror/author-regex-1.0.0.tgz new file mode 100644 index 000000000000..e9cd8510f395 Binary files /dev/null and b/.yarn-offline-mirror/author-regex-1.0.0.tgz differ diff --git a/.yarn-offline-mirror/cli-spinners-1.3.1.tgz b/.yarn-offline-mirror/cli-spinners-1.3.1.tgz new file mode 100644 index 000000000000..c6abd39b3d30 Binary files /dev/null and b/.yarn-offline-mirror/cli-spinners-1.3.1.tgz differ diff --git a/.yarn-offline-mirror/cocoascript-class-0.1.2.tgz b/.yarn-offline-mirror/cocoascript-class-0.1.2.tgz new file mode 100644 index 000000000000..dc2e54d9fa6d Binary files /dev/null and b/.yarn-offline-mirror/cocoascript-class-0.1.2.tgz differ diff --git a/.yarn-offline-mirror/coscript-1.0.0.tgz b/.yarn-offline-mirror/coscript-1.0.0.tgz new file mode 100644 index 000000000000..b2dcdc29a24d Binary files /dev/null and b/.yarn-offline-mirror/coscript-1.0.0.tgz differ diff --git a/.yarn-offline-mirror/cross-spawn-promise-0.10.1.tgz b/.yarn-offline-mirror/cross-spawn-promise-0.10.1.tgz new file mode 100644 index 000000000000..b3ef70116b45 Binary files /dev/null and b/.yarn-offline-mirror/cross-spawn-promise-0.10.1.tgz differ diff --git a/.yarn-offline-mirror/fs.promised-3.0.0.tgz b/.yarn-offline-mirror/fs.promised-3.0.0.tgz new file mode 100644 index 000000000000..c2ee4458f8b6 Binary files /dev/null and b/.yarn-offline-mirror/fs.promised-3.0.0.tgz differ diff --git a/.yarn-offline-mirror/gittar-0.1.1.tgz b/.yarn-offline-mirror/gittar-0.1.1.tgz new file mode 100644 index 000000000000..584247d76835 Binary files /dev/null and b/.yarn-offline-mirror/gittar-0.1.1.tgz differ diff --git a/.yarn-offline-mirror/globby-7.1.1.tgz b/.yarn-offline-mirror/globby-7.1.1.tgz new file mode 100644 index 000000000000..e17f086356ef Binary files /dev/null and b/.yarn-offline-mirror/globby-7.1.1.tgz differ diff --git a/.yarn-offline-mirror/keychain-1.3.0.tgz b/.yarn-offline-mirror/keychain-1.3.0.tgz new file mode 100644 index 000000000000..524b49a73485 Binary files /dev/null and b/.yarn-offline-mirror/keychain-1.3.0.tgz differ diff --git a/.yarn-offline-mirror/ora-1.4.0.tgz b/.yarn-offline-mirror/ora-1.4.0.tgz new file mode 100644 index 000000000000..2506c271864f Binary files /dev/null and b/.yarn-offline-mirror/ora-1.4.0.tgz differ diff --git a/.yarn-offline-mirror/parse-author-2.0.0.tgz b/.yarn-offline-mirror/parse-author-2.0.0.tgz new file mode 100644 index 000000000000..147dd7749554 Binary files /dev/null and b/.yarn-offline-mirror/parse-author-2.0.0.tgz differ diff --git a/.yarn-offline-mirror/promise-polyfill-8.1.0.tgz b/.yarn-offline-mirror/promise-polyfill-8.1.0.tgz new file mode 100644 index 000000000000..89c3ab5756fc Binary files /dev/null and b/.yarn-offline-mirror/promise-polyfill-8.1.0.tgz differ diff --git a/.yarn-offline-mirror/run-sketch-plugin-1.0.3.tgz b/.yarn-offline-mirror/run-sketch-plugin-1.0.3.tgz new file mode 100644 index 000000000000..a19c30426d38 Binary files /dev/null and b/.yarn-offline-mirror/run-sketch-plugin-1.0.3.tgz differ diff --git a/.yarn-offline-mirror/sketch-polyfill-fetch-0.4.5.tgz b/.yarn-offline-mirror/sketch-polyfill-fetch-0.4.5.tgz new file mode 100644 index 000000000000..86efb98dd1c6 Binary files /dev/null and b/.yarn-offline-mirror/sketch-polyfill-fetch-0.4.5.tgz differ diff --git a/.yarn-offline-mirror/skpm-1.2.0.tgz b/.yarn-offline-mirror/skpm-1.2.0.tgz new file mode 100644 index 000000000000..3094bc42a573 Binary files /dev/null and b/.yarn-offline-mirror/skpm-1.2.0.tgz differ diff --git a/.yarn-offline-mirror/webpack-4.31.0.tgz b/.yarn-offline-mirror/webpack-4.31.0.tgz new file mode 100644 index 000000000000..e23773bedfda Binary files /dev/null and b/.yarn-offline-mirror/webpack-4.31.0.tgz differ diff --git a/.yarn-offline-mirror/webpack-merge-4.2.1.tgz b/.yarn-offline-mirror/webpack-merge-4.2.1.tgz new file mode 100644 index 000000000000..a7835e9a01eb Binary files /dev/null and b/.yarn-offline-mirror/webpack-merge-4.2.1.tgz differ diff --git a/.yarn-offline-mirror/yesno-0.2.0.tgz b/.yarn-offline-mirror/yesno-0.2.0.tgz new file mode 100644 index 000000000000..14576677a4fd Binary files /dev/null and b/.yarn-offline-mirror/yesno-0.2.0.tgz differ diff --git a/package.json b/package.json index fd24aa3f49b4..40a23220787d 100644 --- a/package.json +++ b/package.json @@ -94,6 +94,10 @@ "yarn lerna run lint:staged --scope carbon-components-react", "git add" ], + "*.js,!packages/components/**/*.js,!packages/react/**/*.js": [ + "yarn format:staged", + "git add" + ], "*.md": [ "yarn format:staged", "git add" diff --git a/packages/icons/src/svg/16/checkmark--filled.svg b/packages/icons/src/svg/16/checkmark--filled.svg index 86f22872e177..906de6f0ed10 100644 --- a/packages/icons/src/svg/16/checkmark--filled.svg +++ b/packages/icons/src/svg/16/checkmark--filled.svg @@ -8,5 +8,5 @@ - + diff --git a/packages/icons/src/svg/32/checkmark--filled.svg b/packages/icons/src/svg/32/checkmark--filled.svg index 3af4edc9c2b8..858c59ffed0f 100644 --- a/packages/icons/src/svg/32/checkmark--filled.svg +++ b/packages/icons/src/svg/32/checkmark--filled.svg @@ -4,7 +4,7 @@ width="32px" height="32px" viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve"> diff --git a/packages/sketch/.gitignore b/packages/sketch/.gitignore new file mode 100644 index 000000000000..6f0d0fa004ff --- /dev/null +++ b/packages/sketch/.gitignore @@ -0,0 +1 @@ +*.sketchplugin diff --git a/packages/sketch/README.md b/packages/sketch/README.md new file mode 100644 index 000000000000..8374e383a613 --- /dev/null +++ b/packages/sketch/README.md @@ -0,0 +1,103 @@ +# @carbon/sketch + + + + +## Table of Contents + +- [Getting started (developing)](#getting-started-developing) +- [Overview](#overview) + - [Building sketch plugins](#building-sketch-plugins) + - [Project structure](#project-structure) +- [Reference](#reference) +- [Tips & Tricks](#tips--tricks) + + + + +## Getting started (developing) + +When working with this package, you will need to follow a couple of steps to get +started. It's important that you have Sketch installed on your system before +attempting any of these steps. + +1. Run `cd packages/sketch` to go into the package folder +2. Run `yarn build` to build out the initial plugin +3. Run `yarn skpm:link` to link the plugin to your Sketch plugin folder + +Afterwards, you can continue development by running `yarn develop`. + +## Overview + +### Building sketch plugins + +The output of `@carbon/sketch` is a plugin at +`packages/sketch/carbon-elements.sketchplugin`. This artifact is generated by +running `yarn build`. Under the hood, we make use of a tool called +[`skpm`](https://github.com/skpm/skpm) that allows us to write our Sketch +plugins using modern JavaScript language features and modules. + +When using `skpm`, we add a field named `skpm` to our `package.json` so that it +knows details about our plugin, most notably the name of the plugin and a +reference to a `manifest.json` file. This file lists out the capabilities of the +sketch plugin under the `commands` field, and also defines the menu structure th +at should appear for this plugin under the Plugins menu in Sketch. + +Under the `commands` field, we list out commands and define a path to a `script` +and name the `handler` that should be called when running the command. In other +words, if we have a file like: + +```js +// commands/greeting.js +import sketch from 'sketch'; + +export function greeting() { + sketch.UI.message('Hello world!'); +} +``` + +Then in our `manifest.json` we would create an entry under `commands` like: + +```json +{ + "commands": [ + { + "name": "The name of the command" + "identifier": "the.command.identifier", + "script": "commands/greeting.", + "handler": "greeting" + } + ] +} +``` + +_Note: We chose the `greeting` handler because that was what was exported in +`export function greeting() {}`._ + +We later use the `identifier` field in our menu to reference the command. + +### Project structure + +```bash +packages/sketch +├── package.json +└── src + ├── commands # Implementation of commands in `manifest.json` + ├── manifest.json # Define capabilities of Sketch plugin + ├── sharedStyles # Methods for syncing shared layer and text styles + └── tools # Tools for interacting with the Sketch DOM and styles +``` + +## Reference + +- [API Reference](https://developer.sketch.com/reference/api) for the `sketch` + module +- [`Sketch-Headers`](https://github.com/abynim/Sketch-Headers) to determine + methods on internal objects +- [Plugin bundle guide](https://developer.sketch.com/guides/plugin-bundles/) for + structuring a plugin and its menus + +## Tips & Tricks + +- Use `yarn skpm log -f` to tail logs from the Sketch plugin. Useful if you want + to debug using `console.log` layer is removed diff --git a/packages/sketch/package.json b/packages/sketch/package.json new file mode 100644 index 000000000000..a35f23af7da7 --- /dev/null +++ b/packages/sketch/package.json @@ -0,0 +1,34 @@ +{ + "name": "@carbon/sketch", + "description": "Tooling for generating a sketch plugin to bring code to design", + "private": true, + "version": "10.2.0", + "license": "Apache-2.0", + "scripts": { + "build": "cross-env NODE_ENV=production skpm-build", + "clean": "rimraf carbon-elements.sketchplugin", + "develop": "cross-env NODE_ENV=development skpm-build --watch", + "skpm:link": "skpm-link" + }, + "dependencies": { + "@babel/polyfill": "^7.4.4", + "@carbon/colors": "10.2.0", + "@carbon/icon-helpers": "10.2.0", + "@carbon/icons": "10.2.0", + "@carbon/themes": "10.2.0", + "@carbon/type": "10.2.0", + "@skpm/builder": "^0.7.0", + "color-string": "^1.5.3", + "skpm": "^1.2.0" + }, + "devDependencies": { + "cross-env": "^5.2.0", + "rimraf": "^2.6.3" + }, + "skpm": { + "name": "Carbon Elements", + "manifest": "src/manifest.json", + "main": "carbon-elements.sketchplugin", + "assets": [] + } +} diff --git a/packages/sketch/src/commands/colors/generate.js b/packages/sketch/src/commands/colors/generate.js new file mode 100644 index 000000000000..01668bb5da31 --- /dev/null +++ b/packages/sketch/src/commands/colors/generate.js @@ -0,0 +1,94 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { Document, Rectangle, ShapePath, SymbolMaster } from 'sketch/dom'; +import { command } from '../command'; +import { syncColorStyles } from '../../sharedStyles/colors'; +import { findOrCreatePage, selectPage } from '../../tools/page'; +import { groupByKey } from '../../tools/grouping'; + +const ARTBOARD_WIDTH = 40; +const ARTBOARD_HEIGHT = 40; +const ARTBOARD_MARGIN = 8; + +export function generate() { + command('commands/colors/generate', () => { + const document = Document.getSelectedDocument(); + const page = selectPage(findOrCreatePage(document, 'Color')); + const sharedStyles = syncColorStyles(document); + const { blackAndWhite, colors, support } = groupByKey( + sharedStyles, + sharedStyle => { + const { name } = sharedStyle; + const [category, swatch, grade] = name.split('/'); + switch (swatch) { + case 'black': + case 'white': + return 'blackAndWhite'; + case 'yellow': + case 'orange': + return 'support'; + default: + return 'colors'; + } + } + ); + + let X_OFFSET = 0; + let Y_OFFSET = 0; + + for (const sharedStyle of blackAndWhite) { + createSymbolFromSharedStyle(sharedStyle, page, X_OFFSET, Y_OFFSET); + X_OFFSET = X_OFFSET + ARTBOARD_WIDTH + ARTBOARD_MARGIN; + } + + X_OFFSET = 0; + Y_OFFSET = Y_OFFSET + ARTBOARD_HEIGHT + ARTBOARD_MARGIN; + + const swatches = groupByKey(colors, sharedStyle => { + const [category, swatch, grade] = sharedStyle.name.split('/'); + return swatch; + }); + + for (const swatch of Object.keys(swatches)) { + for (const sharedStyle of swatches[swatch]) { + createSymbolFromSharedStyle(sharedStyle, page, X_OFFSET, Y_OFFSET); + X_OFFSET = X_OFFSET + ARTBOARD_WIDTH + ARTBOARD_MARGIN; + } + + X_OFFSET = 0; + Y_OFFSET = Y_OFFSET + ARTBOARD_HEIGHT + ARTBOARD_MARGIN; + } + + for (const sharedStyle of support) { + createSymbolFromSharedStyle(sharedStyle, page, X_OFFSET, Y_OFFSET); + X_OFFSET = X_OFFSET + ARTBOARD_WIDTH + ARTBOARD_MARGIN; + } + }); +} + +function createSymbolFromSharedStyle(sharedStyle, parent, offsetX, offsetY) { + const [category, swatch, grade] = sharedStyle.name.split('/'); + + const colorName = grade ? `${swatch}/${swatch}-${grade}` : swatch; + const rectangle = new ShapePath({ + name: 'Color', + frame: new Rectangle(0, 0, ARTBOARD_WIDTH, ARTBOARD_HEIGHT), + shapeType: ShapePath.ShapeType.Rectangle, + sharedStyleId: sharedStyle.id, + style: sharedStyle.style, + }); + + const artboard = new SymbolMaster({ + parent, + name: `${category}/${colorName}`, + frame: new Rectangle(offsetX, offsetY, ARTBOARD_WIDTH, ARTBOARD_HEIGHT), + layers: [rectangle], + }); + + return artboard; +} diff --git a/packages/sketch/src/commands/colors/index.js b/packages/sketch/src/commands/colors/index.js new file mode 100644 index 000000000000..8b8807840172 --- /dev/null +++ b/packages/sketch/src/commands/colors/index.js @@ -0,0 +1,9 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +export { sync } from './sync'; +export { generate } from './generate'; diff --git a/packages/sketch/src/commands/colors/sync.js b/packages/sketch/src/commands/colors/sync.js new file mode 100644 index 000000000000..6a1ce0980934 --- /dev/null +++ b/packages/sketch/src/commands/colors/sync.js @@ -0,0 +1,17 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { Document } from 'sketch/dom'; +import { command } from '../command'; +import { syncColorStyles } from '../../sharedStyles/colors'; + +export function sync() { + command('commands/colors/sync', () => { + const document = Document.getSelectedDocument(); + syncColorStyles(document); + }); +} diff --git a/packages/sketch/src/commands/command.js b/packages/sketch/src/commands/command.js new file mode 100644 index 000000000000..bf0857ca1256 --- /dev/null +++ b/packages/sketch/src/commands/command.js @@ -0,0 +1,26 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import sketch from 'sketch'; + +/** + * Wrap a given command function for consistent UI messages and development + * runtime logging. + * @param {string} name - the name of the command + * @param {Function} fn - the function to call to run the command + */ +export function command(name, fn) { + const start = Date.now(); + + sketch.UI.message('Hi 👋 We are still working on this! 🚧'); + fn(); + sketch.UI.message('Done! 🎉'); + + if (process.env.NODE_ENV === 'development') { + console.log(`[Carbon Elements] ${name}: Done in ${Date.now() - start}ms`); + } +} diff --git a/packages/sketch/src/commands/icons/generate.js b/packages/sketch/src/commands/icons/generate.js new file mode 100644 index 000000000000..cd8b08d6e9d6 --- /dev/null +++ b/packages/sketch/src/commands/icons/generate.js @@ -0,0 +1,235 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { toString } from '@carbon/icon-helpers'; +import React from 'react'; +import { + Document, + Group, + Rectangle, + Shape, + Style, + SymbolMaster, +} from 'sketch/dom'; +import { command } from '../command'; +import { syncColorStyles } from '../../sharedStyles/colors'; +import { groupByKey } from '../../tools/grouping'; +import { findOrCreatePage, selectPage } from '../../tools/page'; + +const meta = require('@carbon/icons/meta.json'); + +export function generate() { + command('commands/icons/generate', () => { + const document = Document.getSelectedDocument(); + const page = selectPage(findOrCreatePage(document, 'Icons')); + const sharedStyles = syncColorStyles(document); + const [sharedStyle] = sharedStyles.filter( + ({ name }) => name === 'color/black' + ); + + if (!sharedStyle) { + throw new Error( + 'Unexpected error occurred, expected shared style but found none' + ); + } + + const icons = normalize(meta); + const iconNames = Object.keys(icons); + + // To help with debugging, we have `start` and `end` values here to focus on + // specific icon ranges. You can also work on a specific icon by finding + // it's index and setting the value of start to the index and end to the + // index + 1. + // + // To find the index, you can use: + // console.log(iconNames.findIndex(name === 'name-to-find')); // 50 + // And use that value below like: + // const start = 50; + // const end = 51; + // This will allow you to focus only on the icon named 'name-to-find' + const start = 0; + const end = iconNames.length; + + // We keep track of the current X and Y offsets at the top-level, each + // iteration of an icon set should reset the X_OFFSET and update the + // Y_OFFSET with the maximum size in the icon set. + let X_OFFSET = 0; + let Y_OFFSET = 0; + let maxSize = -Infinity; + + const artboards = iconNames.slice(start, end).flatMap((name, i) => { + const sizes = icons[name]; + + X_OFFSET = 0; + if (i !== 0) { + Y_OFFSET = Y_OFFSET + maxSize + 32; + } + maxSize = -Infinity; + + return sizes.map(icon => { + // If our icon has an original size, we will need to render it in the + // original size and then resize it to the appropriate artboard size + const size = icon.original || icon.size; + const descriptor = Object.assign({}, icon.descriptor); + + // We push a transparent rectangle to mirror the "bounding box" found in + // icon artboards that is stripped by our build process. Including this + // makes sure that our icon renders true to the path data + descriptor.content.push({ + elem: 'rect', + attrs: { + width: size, + height: size, + fill: 'none', + }, + }); + + const layer = createSVGLayer(icon.descriptor); + + layer.name = icon.basename; + layer.rect = { + origin: { + x: 0, + y: 0, + }, + size: { + width: icon.size, + height: icon.size, + }, + }; + + let symbolName = + sizes.length !== 1 + ? `category/${name}/${icon.size}` + : `category/${name}`; + + if (icon.original) { + symbolName = `${symbolName}*`; + } + + const artboard = new SymbolMaster({ + name: symbolName, + frame: new Rectangle(X_OFFSET, Y_OFFSET, icon.size, icon.size), + layers: [layer], + }); + + if (size > maxSize) { + maxSize = size; + } + + X_OFFSET = X_OFFSET + icon.size + 8; + + const [group] = artboard.layers; + + // Last layer will be the transparent rectangle we added above + const paths = group.layers.slice(0, -1).map(layer => layer.duplicate()); + + // We split things out into fillPaths and innerPaths, allowing us to + // style them independent of each other in the symbol. Useful for + // two-tone icons. + const { fillPaths = [], innerPaths = [] } = groupByKey( + paths, + (path, i) => { + const node = icon.descriptor.content[i]; + if (node.attrs['data-icon-path'] === 'inner-path') { + return 'innerPaths'; + } + return 'fillPaths'; + } + ); + + let shape; + if (fillPaths.length === 1) { + shape = fillPaths[0]; + shape.name = 'Fill'; + shape.style = sharedStyle.style; + shape.sharedStyleId = sharedStyle.id; + } else { + // If we have multiple fill paths, we need to consolidate them into a + // single Shape so that we can style the icon with one override in the + // symbol + shape = new Shape({ + name: 'Fill', + frame: new Rectangle(0, 0, icon.size, icon.size), + layers: fillPaths, + style: sharedStyle.style, + sharedStyleId: sharedStyle.id, + }); + } + + shape.style.borders = []; + + for (const innerPath of innerPaths) { + innerPath.name = 'Inner Fill'; + innerPath.style = sharedStyle.style; + innerPath.style.opacity = 0; + innerPath.sharedStyleId = sharedStyle.id; + } + + artboard.layers.push(shape, ...innerPaths); + group.remove(); + + return artboard; + }); + }); + + page.layers.push(...artboards); + }); +} + +/** + * Normalize a collection of icons by their basename + * @param {Array} icons + * @return {Object} + */ +function normalize(icons) { + // Collect all icons and group them by their base names. The value of the + // basename key is the array of all sizes for that icon + const iconsByBasename = icons.reduce((acc, icon) => { + // Ignore glyphs + if (!icon.size) { + return acc; + } + // Drop size from prefix + const name = [...icon.prefix.slice(1), icon.basename].join('/'); + if (acc[name]) { + return { + ...acc, + [name]: acc[name].concat(icon).sort(sortBySize), + }; + } + return { + ...acc, + [name]: [icon], + }; + }, {}); + + return iconsByBasename; +} + +function sortBySize(a, b) { + return b.size - a.size; +} + +/** + * Create a layer from an SVG descriptor + * + * Reference: + * https://github.com/airbnb/react-sketchapp/blob/aa3070556c47883974edbc7f78978c421a8199f7/src/jsonUtils/sketchImpl/makeSvgLayer.js#L12 + * + * @param {Object} svg + * @return {Layer} + */ +function createSVGLayer(svg) { + const svgString = NSString.stringWithString(toString(svg)); + const svgData = svgString.dataUsingEncoding(NSUTF8StringEncoding); + const svgImporter = MSSVGImporter.svgImporter(); + svgImporter.prepareToImportFromData(svgData); + const svgLayer = svgImporter.importAsLayer(); + + return svgLayer; +} diff --git a/packages/sketch/src/commands/icons/index.js b/packages/sketch/src/commands/icons/index.js new file mode 100644 index 000000000000..864e1921d9f3 --- /dev/null +++ b/packages/sketch/src/commands/icons/index.js @@ -0,0 +1,8 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +export { generate } from './generate'; diff --git a/packages/sketch/src/commands/index.js b/packages/sketch/src/commands/index.js new file mode 100644 index 000000000000..62ac3cc97bb3 --- /dev/null +++ b/packages/sketch/src/commands/index.js @@ -0,0 +1,17 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import '@babel/polyfill'; + +// We export all commands through one entrypoint to prevent build errors +// triggered by having separate entrypoints. Most notably we would encounter +// parse errors because the bundlers were being generated incorrectly during +// incremental rebuilds. +export { sync as syncColors, generate as generateColors } from './colors'; +export { generate as generateIcons } from './icons'; +export { sync as syncThemes, generate as generateThemes } from './themes'; +export { sync as syncType, generate as generateType } from './type'; diff --git a/packages/sketch/src/commands/themes/generate.js b/packages/sketch/src/commands/themes/generate.js new file mode 100644 index 000000000000..af39a312f2af --- /dev/null +++ b/packages/sketch/src/commands/themes/generate.js @@ -0,0 +1,63 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { Document, Rectangle, ShapePath, SymbolMaster } from 'sketch/dom'; +import { command } from '../command'; +import { findOrCreatePage, selectPage } from '../../tools/page'; +import { groupByKey } from '../../tools/grouping'; +import { syncThemeColorStyles } from '../../sharedStyles/themes'; + +const ARTBOARD_WIDTH = 40; +const ARTBOARD_HEIGHT = 40; + +const ARTBOARD_MARGIN_VERTICAL = 8; +const ARTBOARD_MARGIN_HORIZONTAL = 40; + +export function generate() { + command('commands/themes/generate', () => { + const document = Document.getSelectedDocument(); + const page = selectPage(findOrCreatePage(document, 'Themes')); + const sharedStyles = syncThemeColorStyles(document); + + const tokens = groupByKey(sharedStyles, sharedStyle => { + const [category, token] = sharedStyle.name.split('/'); + return token.trim(); + }); + + let X_OFFSET = 0; + let Y_OFFSET = 0; + + for (const token of Object.keys(tokens)) { + for (const sharedStyle of tokens[token]) { + createSymbolFromSharedStyle(sharedStyle, page, X_OFFSET, Y_OFFSET); + X_OFFSET = X_OFFSET + ARTBOARD_WIDTH + ARTBOARD_MARGIN_HORIZONTAL; + } + + X_OFFSET = 0; + Y_OFFSET = Y_OFFSET + ARTBOARD_HEIGHT + ARTBOARD_MARGIN_VERTICAL; + } + }); +} + +function createSymbolFromSharedStyle(sharedStyle, parent, offsetX, offsetY) { + const rectangle = new ShapePath({ + name: 'Color', + frame: new Rectangle(0, 0, ARTBOARD_WIDTH, ARTBOARD_HEIGHT), + shapeType: ShapePath.ShapeType.Rectangle, + sharedStyleId: sharedStyle.id, + style: sharedStyle.style, + }); + + const artboard = new SymbolMaster({ + parent, + name: sharedStyle.name, + frame: new Rectangle(offsetX, offsetY, ARTBOARD_WIDTH, ARTBOARD_HEIGHT), + layers: [rectangle], + }); + + return artboard; +} diff --git a/packages/sketch/src/commands/themes/index.js b/packages/sketch/src/commands/themes/index.js new file mode 100644 index 000000000000..8b8807840172 --- /dev/null +++ b/packages/sketch/src/commands/themes/index.js @@ -0,0 +1,9 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +export { sync } from './sync'; +export { generate } from './generate'; diff --git a/packages/sketch/src/commands/themes/sync.js b/packages/sketch/src/commands/themes/sync.js new file mode 100644 index 000000000000..2314f035b16d --- /dev/null +++ b/packages/sketch/src/commands/themes/sync.js @@ -0,0 +1,17 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { Document } from 'sketch/dom'; +import { command } from '../command'; +import { syncThemeColorStyles } from '../../sharedStyles/themes'; + +export function sync() { + command('commands/themes/sync', () => { + const document = Document.getSelectedDocument(); + syncThemeColorStyles(document); + }); +} diff --git a/packages/sketch/src/commands/type/generate.js b/packages/sketch/src/commands/type/generate.js new file mode 100644 index 000000000000..781b89342de2 --- /dev/null +++ b/packages/sketch/src/commands/type/generate.js @@ -0,0 +1,39 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import sketch from 'sketch'; +import { Document, Rectangle, Text } from 'sketch/dom'; +import { command } from '../command'; +import { findOrCreatePage, selectPage } from '../../tools/page'; +import { syncTextStyles } from '../../sharedStyles/type'; + +const TEXT_LAYER_WIDTH = 500; +const TEXT_LAYER_HEIGHT = 75; +const TEXT_MARGIN = 16; + +export function generate() { + command('commands/type/generate', () => { + const document = Document.getSelectedDocument(); + const page = selectPage(findOrCreatePage(document, 'Type')); + const sharedStyles = syncTextStyles(document); + + let Y_OFFSET = 0; + + for (const sharedStyle of sharedStyles) { + const layer = new Text({ + name: sharedStyle.name, + frame: new Rectangle(0, Y_OFFSET, TEXT_LAYER_WIDTH, TEXT_LAYER_HEIGHT), + style: sharedStyle.style, + sharedStyleId: sharedStyle.id, + parent: page, + text: sharedStyle.name, + }); + + Y_OFFSET = Y_OFFSET + TEXT_LAYER_HEIGHT + TEXT_MARGIN; + } + }); +} diff --git a/packages/sketch/src/commands/type/index.js b/packages/sketch/src/commands/type/index.js new file mode 100644 index 000000000000..8b8807840172 --- /dev/null +++ b/packages/sketch/src/commands/type/index.js @@ -0,0 +1,9 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +export { sync } from './sync'; +export { generate } from './generate'; diff --git a/packages/sketch/src/commands/type/sync.js b/packages/sketch/src/commands/type/sync.js new file mode 100644 index 000000000000..98c996d0c934 --- /dev/null +++ b/packages/sketch/src/commands/type/sync.js @@ -0,0 +1,17 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { Document } from 'sketch/dom'; +import { command } from '../command'; +import { syncTextStyles } from '../../sharedStyles/type'; + +export function sync() { + command('commands/type/sync', () => { + const document = Document.getSelectedDocument(); + syncTextStyles(document); + }); +} diff --git a/packages/sketch/src/manifest.json b/packages/sketch/src/manifest.json new file mode 100644 index 000000000000..3eca1402fba9 --- /dev/null +++ b/packages/sketch/src/manifest.json @@ -0,0 +1,81 @@ +{ + "identifier": "com.ibm.carbon.elements", + "compatibleVersion": "3", + "bundleVersion": 1, + "name": "Carbon Elements 🎨", + "commands": [ + { + "name": "Sync shared layer styles", + "identifier": "carbon.elements.colors.sync", + "script": "commands/index.js", + "handler": "syncColors" + }, + { + "name": "Generate color page", + "identifier": "carbon.elements.colors.generate", + "script": "commands/index.js", + "handler": "generateColors" + }, + { + "name": "Sync shared layer styles", + "identifier": "carbon.elements.themes.sync", + "script": "commands/index.js", + "handler": "syncThemes" + }, + { + "name": "Generate themes page", + "identifier": "carbon.elements.themes.generate", + "script": "commands/index.js", + "handler": "generateThemes" + }, + { + "name": "Sync shared layer styles", + "identifier": "carbon.elements.type.sync", + "script": "commands/index.js", + "handler": "syncType" + }, + { + "name": "Generate type page", + "identifier": "carbon.elements.type.generate", + "script": "commands/index.js", + "handler": "generateType" + }, + { + "name": "Generate icon page and symbols", + "identifier": "carbon.elements.icons.generate", + "script": "commands/index.js", + "handler": "generateIcons" + } + ], + "menu": { + "items": [ + { + "title": "Colors", + "items": [ + "carbon.elements.colors.sync", + "carbon.elements.colors.generate" + ] + }, + { + "title": "Themes", + "items": [ + "carbon.elements.themes.sync", + "carbon.elements.themes.generate" + ] + }, + { + "title": "Icons", + "items": [ + "carbon.elements.icons.generate" + ] + }, + { + "title": "Type", + "items": [ + "carbon.elements.type.sync", + "carbon.elements.type.generate" + ] + } + ] + } +} diff --git a/packages/sketch/src/sharedStyles/colors.js b/packages/sketch/src/sharedStyles/colors.js new file mode 100644 index 000000000000..e0c15f930630 --- /dev/null +++ b/packages/sketch/src/sharedStyles/colors.js @@ -0,0 +1,121 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { colors } from '@carbon/colors'; +import { formatTokenName } from '@carbon/themes'; +import { SharedStyle, Style } from 'sketch/dom'; +import { syncSharedStyle } from '../tools/sharedStyles'; + +// We separate out certain colors that are not a part of the primary swatches +// that we need to render +const { black, white, orange, yellow, ...swatches } = colors; +const colorNames = Object.keys(colors); + +// Color names in JavaScript will be camelCase, so we need to map them over to +// the token name. For example: `warmGray` becomes `warm-gray` +const formattedSwatchNames = colorNames.reduce( + (acc, key, i) => ({ + ...acc, + [formatTokenName(key)]: colorNames[i], + }), + {} +); + +// We need to build up our expected shared styles from code to diff with what +// currently exists in the document. For this case, we'll use the shared style +// name as the key and the value from the swatch as the expected value +const expectedSharedStyles = Object.keys(swatches).reduce((acc, swatch) => { + const name = formatTokenName(swatch); + const swatchStyles = Object.keys(swatches[swatch]).reduce((acc, grade) => { + return { + ...acc, + [formatSharedStyleName(name, grade)]: swatches[swatch][grade], + }; + }, {}); + + return { + ...acc, + ...swatchStyles, + }; +}, {}); + +expectedSharedStyles[formatSharedStyleName('black')] = black['100']; +expectedSharedStyles[formatSharedStyleName('white')] = white['0']; +expectedSharedStyles[formatSharedStyleName('orange')] = orange['40']; +expectedSharedStyles[formatSharedStyleName('yellow')] = yellow['20']; + +/** + * Sync color shared styles to the given document and return the result + * @param {Document} document + * @return {Array} + */ +export function syncColorStyles(document) { + const { sharedLayerStyles } = document; + const existingStyles = sharedLayerStyles.filter(({ name, style }) => { + const fill = style.fills[0]; + // Colors in Sketch are #RRGGBB plus opacity, so typically they are + // #RRGGBBFF + const color = fill.color.slice(0, -2); + return expectedSharedStyles[name] && expectedSharedStyles[name] === color; + }); + + // Exit early if everything is the same + if (existingStyles.length === Object.keys(expectedSharedStyles).length) { + return existingStyles; + } + + const sharedStyles = Object.keys(swatches).flatMap(swatchName => { + const name = formatTokenName(swatchName); + return Object.keys(swatches[swatchName]).map(grade => { + return syncColorStyle( + document, + formatSharedStyleName(name, grade), + swatches[swatchName][grade] + ); + }); + }); + + const singleColors = [ + ['black', black['100']], + ['white', white['0']], + ['orange', orange['40']], + ['yellow', yellow['20']], + ].map(([name, value]) => { + return syncColorStyle(document, formatSharedStyleName(name), value); + }); + + return sharedStyles.concat(singleColors); +} + +/** + * Our shared style name will need to have the `color` namespace alongside a + * name for the swatch and an optional grade. + * @param {string} name + * @param {string?} grade + * @return {string} + */ +function formatSharedStyleName(name, grade) { + return ['color', name, grade].filter(Boolean).join('/'); +} + +/** + * Sync the given color value as a shared style for the document + * @param {Document} document + * @param {string} name + * @param {string} value + * @return {SharedStyle} + */ +function syncColorStyle(document, name, value) { + return syncSharedStyle(document, name, { + fills: [ + { + color: value, + fillType: Style.FillType.Color, + }, + ], + }); +} diff --git a/packages/sketch/src/sharedStyles/themes.js b/packages/sketch/src/sharedStyles/themes.js new file mode 100644 index 000000000000..6f8bb2151e12 --- /dev/null +++ b/packages/sketch/src/sharedStyles/themes.js @@ -0,0 +1,118 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { white, g10, g90, g100, formatTokenName } from '@carbon/themes'; +import color from 'color-string'; +import { SharedStyle, Style } from 'sketch/dom'; +import { syncSharedStyle } from '../tools/sharedStyles'; + +/** + * Sync theme color shared styles to the given document and return the result + * @param {Document} document + * @return {Array} + */ +export function syncThemeColorStyles(document) { + const themes = { + 'White theme': white, + 'Gray 10 theme': g10, + 'Gray 90 theme': g90, + 'Gray 100 theme': g100, + }; + + const { sharedLayerStyles } = document; + const existingStyles = sharedLayerStyles.filter(({ name, style }) => { + const [category, token] = name.split('/').map(value => value.trim()); + + if (!themes[category]) { + return false; + } + + const expected = color.get.rgb(themes[category][formatSymbolName(token)]); + const actual = color.get.rgb(style.fills[0].color); + + for (let i = 0; i < expected.length; i++) { + if (actual[i] !== expected[i]) { + return false; + } + } + + return true; + }); + const expectedSharedStyles = Object.keys(themes).reduce((acc, theme) => { + const count = Object.keys(themes[theme]).length; + return acc + count; + }, 0); + + // Exit early if everything is the same + if (existingStyles.length === expectedSharedStyles) { + return existingStyles; + } + + const sharedStyles = Object.keys(themes).flatMap(theme => { + return Object.keys(themes[theme]).map(token => { + const name = `${theme} / ${formatTokenName(token)}`; + return syncColorStyle(document, name, themes[theme][token]); + }); + }); + + return sharedStyles; +} + +/** + * Sync the given color value as a shared style for the document + * @param {Document} document + * @param {string} name + * @param {string} value + * @return {SharedStyle} + */ +function syncColorStyle(document, name, value) { + return syncSharedStyle(document, name, { + fills: [ + { + color: value, + fillType: Style.FillType.Color, + }, + ], + }); +} + +const keywords = ['ui']; + +/** + * Transform a formatted token name back to its JavaScript value to look up the + * expected value for a token from code + * @param {string} token + * @return {string} + */ +function formatSymbolName(token) { + const parts = token.split('-'); + let result = ''; + + for (let i = 0; i < parts.length; i++) { + const part = parts[i]; + + if (i === 0) { + result = part; + continue; + } + + if (keywords.indexOf(part) !== -1) { + result += part.toUpperCase(); + continue; + } + + if (isNaN(part)) { + result += part[0].toUpperCase(); + result += part.slice(1); + continue; + } + + result += part; + } + + return result; +} diff --git a/packages/sketch/src/sharedStyles/type.js b/packages/sketch/src/sharedStyles/type.js new file mode 100644 index 000000000000..dc466f344fa0 --- /dev/null +++ b/packages/sketch/src/sharedStyles/type.js @@ -0,0 +1,97 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { formatTokenName } from '@carbon/themes'; +import { styles } from '@carbon/type'; +import { SharedStyle } from 'sketch/dom'; +import { syncSharedStyle } from '../tools/sharedStyles'; + +const fontWeightTable = { + // Light + 300: 3, + // Regular + 400: 4, + // Medium + 500: 6, + // Semi-bold + 600: 8, + // Bold + 700: 9, +}; +const expressiveTokens = new Set(['display', 'quotation', 'expressive']); + +/** + * Sync text shared styles to the given document and return the result + * @param {Document} document + * @return {Array} + */ +export function syncTextStyles(document) { + return Object.keys(styles) + .filter(token => { + for (const pattern of expressiveTokens) { + if (token.includes(pattern)) { + return false; + } + } + return true; + }) + .map(token => { + const name = formatSharedStyleName(token); + const style = convertTypeStyle(token, styles[token]); + const sharedTextStyle = syncSharedStyle( + document, + name, + style, + SharedStyle.StyleType.Text + ); + + sharedTextStyle.style.textColor = '#000000ff'; + + return sharedTextStyle; + }); +} + +/** + * Format the given token to a value for a shared style name + * @param {string} token + * @return {string} + */ +function formatSharedStyleName(token) { + const parts = formatTokenName(token).split('-'); + if (parts.length === 2) { + return parts.join('-'); + } + + const [category, name, grade] = parts; + if (category !== 'productive') { + return parts.join('-'); + } + + return `${category}/${name}-${grade}`; +} + +/** + * Convert a given token and its style to a format used by Sketch + * @param {string} token + * @param {Object} style + * @return {Object} + */ +function convertTypeStyle(token, style) { + const fontSize = parseFloat(style.fontSize, 10) * 16; + const fontWeight = fontWeightTable[style.fontWeight]; + const fontFamily = token.includes('code') ? 'IBM Plex Mono' : 'IBM Plex Sans'; + const kerning = parseFloat(style.letterSpacing, 10); + const lineHeight = parseFloat(style.lineHeight, 10) * 16; + + return { + fontFamily, + fontSize, + fontWeight, + kerning, + lineHeight, + }; +} diff --git a/packages/sketch/src/tools/grouping.js b/packages/sketch/src/tools/grouping.js new file mode 100644 index 000000000000..c606e730cfb8 --- /dev/null +++ b/packages/sketch/src/tools/grouping.js @@ -0,0 +1,42 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * Sort a collection by keys determined by a sorter. Useful for organizing a + * flat array by figuring out a key for each element and grouping that element + * along with others that have the same key. + * + * @param {Array} collection + * @param {Function} sorter + * @return {Array} + * @example + * const array = [1, 2, 3, 4]; + * const { even, odd } = groupByKey(array, number => { + * if (number % 2 === 0) { + * return 'even'; + * } + * return 'odd'; + * }); + * console.log(even); // [2, 4] + * console.log(odd); // [1, 3] + */ +export function groupByKey(collection, sorter) { + const result = {}; + + for (let i = 0; i < collection.length; i++) { + const element = collection[i]; + const key = sorter(element, i); + + if (!result[key]) { + result[key] = []; + } + + result[key].push(element); + } + + return result; +} diff --git a/packages/sketch/src/tools/page.js b/packages/sketch/src/tools/page.js new file mode 100644 index 000000000000..17f902482b12 --- /dev/null +++ b/packages/sketch/src/tools/page.js @@ -0,0 +1,37 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { Document, Page } from 'sketch/dom'; + +/** + * Find or create a page for the given document context and page name + * @param {Document} document + * @param {string} name + * @return {Page} + */ +export function findOrCreatePage(document, name) { + const [page] = document.pages.filter(page => page.name === name); + + if (page) { + page.remove(); + } + + return new Page({ + name, + parent: document, + }); +} + +/** + * Select the given page, making it the active page in the document + * @param {Page} page + * @return {Page} + */ +export function selectPage(page) { + page.selected = true; + return page; +} diff --git a/packages/sketch/src/tools/sharedStyles.js b/packages/sketch/src/tools/sharedStyles.js new file mode 100644 index 000000000000..498ea6f96170 --- /dev/null +++ b/packages/sketch/src/tools/sharedStyles.js @@ -0,0 +1,53 @@ +/** + * Copyright IBM Corp. 2018, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { SharedStyle } from 'sketch/dom'; + +/** + * Sync a shared style within a document. + * @param {Document} document + * @param {string} name + * @param {Object} style + * @param {StyleType?} styleType + * @return {SharedStyle} + */ +export function syncSharedStyle( + document, + name, + style, + styleType = SharedStyle.StyleType.Layer +) { + // Figure out the type of shared style and try and find if we have already + // created a shared style with the given name + const documentSharedStyles = + styleType === SharedStyle.StyleType.Layer + ? document.sharedLayerStyles + : document.sharedTextStyles; + const [sharedStyle] = Array.from(documentSharedStyles).filter(sharedStyle => { + return sharedStyle.name === name; + }); + + // If none exists, we can create one from scratch + if (!sharedStyle) { + return SharedStyle.fromStyle({ + name, + style, + styleType, + document, + }); + } + + // Otherwise, we'll go and update values of the sharedStyle with the given + // style if the values are different + Object.keys(style).forEach(key => { + if (sharedStyle.style[key] !== style[key]) { + sharedStyle.style[key] = style[key]; + } + }); + + return sharedStyle; +} diff --git a/yarn.lock b/yarn.lock index 39af50385c45..cdd6b26cc8df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -333,7 +333,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/plugin-proposal-async-generator-functions@^7.1.0", "@babel/plugin-proposal-async-generator-functions@^7.2.0": +"@babel/plugin-proposal-async-generator-functions@^7.0.0", "@babel/plugin-proposal-async-generator-functions@^7.1.0", "@babel/plugin-proposal-async-generator-functions@^7.2.0": version "7.2.0" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz#b289b306669dce4ad20b0252889a15768c9d417e" dependencies: @@ -873,6 +873,14 @@ "@babel/helper-regex" "^7.4.4" regexpu-core "^4.5.4" +"@babel/polyfill@^7.4.4": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/polyfill/-/polyfill-7.4.4.tgz#78801cf3dbe657844eeabf31c1cae3828051e893" + integrity sha512-WlthFLfhQQhh+A2Gn5NSFl0Huxz36x86Jn+E9OW7ibK8edKPq+KLy4apM1yDpQ8kJOVi1OVjpP4vSDLdrI04dg== + dependencies: + core-js "^2.6.5" + regenerator-runtime "^0.13.2" + "@babel/preset-env@7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.1.0.tgz#e67ea5b0441cfeab1d6f41e9b5c79798800e8d11" @@ -2308,6 +2316,68 @@ dependencies: any-observable "^0.3.0" +"@skpm/babel-preset@0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@skpm/babel-preset/-/babel-preset-0.2.1.tgz#1e0404e058514d72adebe98163b69b0bb1d737e4" + integrity sha512-bIG9JE0rdSuWh5QMyxIXKUPZUXI2BjXxmI1/dxcRNUK2IweZ9vvuuP7IMaplxPYqZgFqSuj1HAmX1uP/CG9YOw== + dependencies: + "@babel/plugin-proposal-async-generator-functions" "^7.0.0" + "@babel/plugin-proposal-object-rest-spread" "^7.0.0" + "@babel/preset-env" "^7.0.0" + "@babel/preset-react" "^7.0.0" + +"@skpm/builder@^0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@skpm/builder/-/builder-0.7.0.tgz#483a871aa7c436c2a88e8e2069c81a0a74045d6e" + integrity sha512-dpYFQIGLKmSRFWBxmS2zItdFhb+b41Je+9YpyrJJTdyHDQLdSY284hinXESdqyuStUr3lqGXgZfZJpTF0hUw0Q== + dependencies: + "@babel/core" "^7.4.3" + "@skpm/babel-preset" "0.2.1" + "@skpm/file-loader" "^2.0.1" + "@skpm/internal-utils" "^0.1.14" + "@skpm/nib-loader" "^0.1.1" + babel-loader "^8.0.5" + chalk "^2.4.1" + globby "^9.2.0" + mkdirp "^0.5.1" + parse-author "2.0.0" + promise-polyfill "^8.1.0" + run-sketch-plugin "^1.0.0" + semver "^6.0.0" + sketch-polyfill-fetch "^0.4.3" + terser-webpack-plugin "^1.2.3" + webpack "^4.29.6" + webpack-merge "^4.2.1" + webpack-sources "^1.3.0" + yargs "^13.2.2" + +"@skpm/file-loader@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@skpm/file-loader/-/file-loader-2.0.1.tgz#afd7624a77eb567550d7cb88f5a6e68a12785e3f" + integrity sha512-Xdv6dPqZu+fhNEZE4/uR9+97uqWfOiXt4E8fdvx2muWwhzs8jJHhc9/PO/9b/6eARbiS4A2W5s/FJC2bzgP0ag== + dependencies: + loader-utils "^1.0.2" + schema-utils "^0.4.5" + +"@skpm/internal-utils@^0.1.14": + version "0.1.14" + resolved "https://registry.yarnpkg.com/@skpm/internal-utils/-/internal-utils-0.1.14.tgz#e2a9c8fd8307c9b7ff3acd434377c18a828fb153" + integrity sha512-6++6bVgo5cc9E34AxZW7DytuNBgPhcn//HhiN0fKOvyvv06q4RqSAL6vun0hpdt96nPLtJe3/gF4G4lARQ/jPA== + dependencies: + chalk "^2.4.1" + js-yaml "^3.13.1" + object-assign "*" + yesno "0.2.0" + +"@skpm/nib-loader@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@skpm/nib-loader/-/nib-loader-0.1.1.tgz#7cf31a0831d75d2ecf3832aea3c58cee43e41d82" + integrity sha512-EcrJk8i4DF/OzQx2P5Y8WC43eOL7jLElG6PkZ8lPLdfliMd9gehiLjfXBlDwEXj6pxH+zgydTB+9HEERQDZoRg== + dependencies: + cocoascript-class "^0.1.2" + loader-utils "^1.0.2" + schema-utils "^0.4.5" + "@storybook/addon-a11y@^4.1.18": version "4.1.18" resolved "https://registry.yarnpkg.com/@storybook/addon-a11y/-/addon-a11y-4.1.18.tgz#2194637735fe48fd5602790718193e5ac0e0c16d" @@ -3978,6 +4048,11 @@ atob@^2.1.1: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== +author-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/author-regex/-/author-regex-1.0.0.tgz#d08885be6b9bbf9439fe087c76287245f0a81450" + integrity sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA= + autolinker@~0.15.0: version "0.15.3" resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.15.3.tgz#342417d8f2f3461b14cf09088d5edf8791dc9832" @@ -4199,7 +4274,7 @@ babel-loader@8.0.4: mkdirp "^0.5.1" util.promisify "^1.0.0" -babel-loader@^8.0.0, babel-loader@^8.0.4: +babel-loader@^8.0.0, babel-loader@^8.0.4, babel-loader@^8.0.5: version "8.0.6" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== @@ -5710,6 +5785,11 @@ cli-cursor@^2.0.0, cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" +cli-spinners@^1.0.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.3.1.tgz#002c1990912d0d59580c93bd36c056de99e4259a" + integrity sha512-1QL4544moEsDVH9T/l6Cemov/37iv1RtoKf7NJ04A60+4MREXNfx/QvavbH6QoGdsD4N4Mwy49cmaINR/o2mdg== + cli-table2@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/cli-table2/-/cli-table2-0.2.0.tgz#2d1ef7f218a0e786e214540562d4bd177fe32d97" @@ -5878,6 +5958,11 @@ coa@~1.0.1: dependencies: q "^1.1.2" +cocoascript-class@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/cocoascript-class/-/cocoascript-class-0.1.2.tgz#dab25f20389946d9986c1812b88ac3783eec42d3" + integrity sha1-2rJfIDiZRtmYbBgSuIrDeD7sQtM= + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -5931,7 +6016,7 @@ color-string@^0.3.0: dependencies: color-name "^1.0.0" -color-string@^1.5.2: +color-string@^1.5.2, color-string@^1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== @@ -6370,7 +6455,7 @@ core-js@^1.0.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-1.2.7.tgz#652294c14651db28fa93bd2d5ff2983a4f08c636" integrity sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY= -core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0: +core-js@^2.2.0, core-js@^2.4.0, core-js@^2.5.0, core-js@^2.6.5: version "2.6.8" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.8.tgz#dc3a1e633a04267944e0cb850d3880f340248139" integrity sha512-RWlREFU74TEkdXzyl1bka66O3kYp8jeTXrvJZDzVVMH8AiHUSOFpL1yfhQJ+wHocAm1m+4971W1PPzfLuCv1vg== @@ -6390,6 +6475,11 @@ core-util-is@1.0.2, core-util-is@^1.0.0, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +coscript@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/coscript/-/coscript-1.0.0.tgz#1a0ef8d5f8b4a67901b97ae59bd2f51e6cc6b0f1" + integrity sha1-Gg741fi0pnkBuXrlm9L1HmzGsPE= + cosmiconfig@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" @@ -6478,10 +6568,18 @@ create-react-class@^15.6.2: cross-env@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.2.0.tgz#6ecd4c015d5773e614039ee529076669b9d126f2" + integrity sha512-jtdNFfFW1hB7sMhr/H6rW1Z45LFqyI431m3qU6bFXcQ3Eh7LtBuG3h74o7ohHZ3crrRkkqHlo4jYHFPcjroANg== dependencies: cross-spawn "^6.0.5" is-windows "^1.0.0" +cross-spawn-promise@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/cross-spawn-promise/-/cross-spawn-promise-0.10.1.tgz#db9cb4c50c60b72a15be049b78122ce382d87b10" + integrity sha1-25y0xQxgtyoVvgSbeBIs44LYexA= + dependencies: + cross-spawn "^5.1.0" + cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -6509,7 +6607,7 @@ cross-spawn@^4.0.2: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^5.0.1: +cross-spawn@^5.0.1, cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= @@ -9110,6 +9208,11 @@ fs-write-stream-atomic@^1.0.8: imurmurhash "^0.1.4" readable-stream "1 || 2" +fs.promised@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fs.promised/-/fs.promised-3.0.0.tgz#ab77379f7c1ad0939e1262a8c2ced93fa6c39d3b" + integrity sha1-q3c3n3wa0JOeEmKows7ZP6bDnTs= + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -9352,6 +9455,14 @@ github-from-package@0.0.0: version "0.0.0" resolved "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" +gittar@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/gittar/-/gittar-0.1.1.tgz#d6993ea6160a86c8b7f3de722a61f73bc99e14b4" + integrity sha1-1pk+phYKhsi3895yKmH3O8meFLQ= + dependencies: + mkdirp "^0.5.1" + tar "^4.4.1" + glob-base@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" @@ -9553,6 +9664,18 @@ globby@^6.0.0, globby@^6.1.0: pify "^2.0.0" pinkie-promise "^2.0.0" +globby@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" + integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= + dependencies: + array-union "^1.0.1" + dir-glob "^2.0.0" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + globby@^8.0.1: version "8.0.2" resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" @@ -12431,7 +12554,7 @@ jsx-ast-utils@^2.0.1, jsx-ast-utils@^2.1.0: dependencies: array-includes "^3.0.3" -jszip@^3.1.3: +jszip@^3.1.3, jszip@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.2.1.tgz#c5d32df7274042282b157efb16e522b43435e01a" integrity sha512-iCMBbo4eE5rb1VCpm5qXOAaUiRKRUKiItn8ah2YQQx9qymmSAY98eyQfioChEYcVQLh0zxJ3wS4A0mh90AVPvw== @@ -12549,6 +12672,11 @@ kew@^0.7.0: resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" integrity sha1-edk9LTM2PW/dKXCzNdkUGtWR15s= +keychain@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/keychain/-/keychain-1.3.0.tgz#ccb8ddc64a62f34d541ac25e612186442a432410" + integrity sha1-zLjdxkpi801UGsJeYSGGRCpDJBA= + keycode@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04" @@ -14720,7 +14848,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@4.X, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@*, object-assign@4.X, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= @@ -14942,6 +15070,16 @@ optionator@^0.8.1, optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" +ora@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ora/-/ora-1.4.0.tgz#884458215b3a5d4097592285f93321bb7a79e2e5" + integrity sha512-iMK1DOQxzzh2MBlVsU42G80mnrvUhqsMh74phHtDlrcTZPK0pH6o7l7DRshK+0YsxDyEuaOkziVdvM3T0QTzpw== + dependencies: + chalk "^2.1.0" + cli-cursor "^2.1.0" + cli-spinners "^1.0.1" + log-symbols "^2.1.0" + ordered-read-streams@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" @@ -15229,6 +15367,13 @@ parse-asn1@^5.0.0: pbkdf2 "^3.0.3" safe-buffer "^5.1.1" +parse-author@2.0.0, parse-author@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-author/-/parse-author-2.0.0.tgz#d3460bf1ddd0dfaeed42da754242e65fb684a81f" + integrity sha1-00YL8d3Q367tQtp1QkLmX7aEqB8= + dependencies: + author-regex "^1.0.0" + parse-entities@^1.0.2, parse-entities@^1.1.0, parse-entities@^1.1.2: version "1.2.1" resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.1.tgz#2c761ced065ba7dc68148580b5a225e4918cdd69" @@ -16390,6 +16535,11 @@ promise-polyfill@^6.0.1: resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-6.1.0.tgz#dfa96943ea9c121fca4de9b5868cb39d3472e057" integrity sha1-36lpQ+qcEh/KTem1hoyznTRy4Fc= +promise-polyfill@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.0.tgz#30059da54d1358ce905ac581f287e184aedf995d" + integrity sha512-OzSf6gcCUQ01byV4BgwyUCswlaQQ6gzXc23aLQWhicvfX9kfsUiUhgt3CCQej8jDnl8/PhGF31JdHX2/MzF3WA== + promise-retry@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" @@ -17974,6 +18124,13 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +run-sketch-plugin@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-sketch-plugin/-/run-sketch-plugin-1.0.3.tgz#2eb6112d2b0870adfb03fce8310ade76d7fd8f52" + integrity sha1-LrYRLSsIcK37A/zoMQredtf9j1I= + dependencies: + coscript "^1.0.0" + rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" @@ -18580,6 +18737,36 @@ sisteransi@^1.0.0: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.0.tgz#77d9622ff909080f1c19e5f4a1df0c1b0a27b88c" integrity sha512-N+z4pHB4AmUv0SjveWRd6q1Nj5w62m5jodv+GD8lvmbY/83T/rpbJGZOnK5T149OldDj4Db07BSv9xY4K6NTPQ== +sketch-polyfill-fetch@^0.4.3: + version "0.4.5" + resolved "https://registry.yarnpkg.com/sketch-polyfill-fetch/-/sketch-polyfill-fetch-0.4.5.tgz#04cc50943444e45343295204cd4b3b070d448256" + integrity sha512-5iTw1k8eu2BtiDVy8JMMR+uV8hxamb0Ib3Q1Ob9MbDnMm9RocyaDGNCaHs8loKnB69i9fCchMboO0pMR6QjGpQ== + +skpm@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/skpm/-/skpm-1.2.0.tgz#fa50465758c17533dc5c9a15be02e99584bc5b95" + integrity sha512-Y1b27m/jx6tDbwcx1Sr3slmYrP47fC8UnCdo4somdXid/fxHzLaoxpgSADgKNZ3emNUrsTvC/cV9oxORyhx26Q== + dependencies: + "@skpm/internal-utils" "^0.1.14" + chalk "^2.4.2" + cross-spawn-promise "^0.10.1" + fs.promised "^3.0.0" + gittar "^0.1.1" + globby "^7.1.1" + inquirer "^6.2.0" + is-ci "^2.0.0" + jszip "^3.2.1" + keychain "^1.3.0" + log-symbols "^2.2.0" + opn "^5.4.0" + ora "^1.4.0" + parse-author "^2.0.0" + request "^2.88.0" + update-notifier "^2.5.0" + which "^1.3.1" + xml2js "^0.4.17" + yargs "^13.2.2" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -19673,7 +19860,7 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^4, tar@^4.4.8: +tar@^4, tar@^4.4.1, tar@^4.4.8: version "4.4.8" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" dependencies: @@ -19709,7 +19896,7 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" -terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.2.0: +terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.2.0, terser-webpack-plugin@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz#3f98bc902fac3e5d0de730869f50668561262ec8" dependencies: @@ -21051,6 +21238,13 @@ webpack-log@^2.0.0: ansi-colors "^3.0.0" uuid "^3.3.2" +webpack-merge@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.1.tgz#5e923cf802ea2ace4fd5af1d3247368a633489b4" + integrity sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw== + dependencies: + lodash "^4.17.5" + webpack-sources@^1.1.0, webpack-sources@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.3.0.tgz#2a28dcb9f1f45fe960d8f1493252b5ee6530fa85" @@ -21089,6 +21283,36 @@ webpack@^4.23.1, webpack@^4.25.1: watchpack "^1.5.0" webpack-sources "^1.3.0" +webpack@^4.29.6: + version "4.31.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.31.0.tgz#ae201d45f0571336e42d1c2b5c8ab56c4d3b0c63" + integrity sha512-n6RVO3X0LbbipoE62akME9K/JI7qYrwwufs20VvgNNpqUoH4860KkaxJTbGq5bgkVZF9FqyyTG/0WPLH3PVNJA== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/wasm-edit" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + acorn "^6.0.5" + acorn-dynamic-import "^4.0.0" + ajv "^6.1.0" + ajv-keywords "^3.1.0" + chrome-trace-event "^1.0.0" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.0" + json-parse-better-errors "^1.0.2" + loader-runner "^2.3.0" + loader-utils "^1.1.0" + memory-fs "~0.4.1" + micromatch "^3.1.8" + mkdirp "~0.5.0" + neo-async "^2.5.0" + node-libs-browser "^2.0.0" + schema-utils "^1.0.0" + tapable "^1.1.0" + terser-webpack-plugin "^1.1.0" + watchpack "^1.5.0" + webpack-sources "^1.3.0" + websocket-driver@>=0.5.1: version "0.7.0" resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.0.tgz#0caf9d2d755d93aee049d4bdd0d3fe2cca2a24eb" @@ -21583,6 +21807,11 @@ yeast@0.1.2: resolved "https://registry.yarnpkg.com/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= +yesno@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/yesno/-/yesno-0.2.0.tgz#acc6c6b57b5ef88279a83cd394be9dc5d2317b7a" + integrity sha512-A66RIAOz+nP2hFpXfULwr57yubsWjEXw7ay8XL5a1AA6FpxiEDllKCnx9vCFDhN5TviTrF9yIfBwPskW3x9jxw== + yup@^0.27.0: version "0.27.0" resolved "https://registry.yarnpkg.com/yup/-/yup-0.27.0.tgz#f8cb198c8e7dd2124beddc2457571329096b06e7"