* Better rollup messages in console * Remove 'docs folder not found' warning * Show production message * fix codacyversion-14
@@ -105,7 +105,8 @@ def make_asset_dirs(make_copy=False, restore=False): | |||||
shutil.rmtree(target) | shutil.rmtree(target) | ||||
os.symlink(source, target) | os.symlink(source, target) | ||||
else: | else: | ||||
warnings.warn('Source {source} does not exist.'.format(source = source)) | |||||
# warnings.warn('Source {source} does not exist.'.format(source = source)) | |||||
pass | |||||
def build(no_compress=False, verbose=False): | def build(no_compress=False, verbose=False): | ||||
assets_path = os.path.join(frappe.local.sites_path, "assets") | assets_path = os.path.join(frappe.local.sites_path, "assets") | ||||
@@ -1,9 +1,9 @@ | |||||
{ | { | ||||
"name": "frappe", | "name": "frappe", | ||||
"scripts": { | "scripts": { | ||||
"build": "rollup -c --silent", | |||||
"production": "FRAPPE_ENV=production rollup -c", | |||||
"watch": "rollup -c -w" | |||||
"build": "node rollup/build.js", | |||||
"production": "FRAPPE_ENV=production node rollup/build.js", | |||||
"watch": "node rollup/watch.js" | |||||
}, | }, | ||||
"repository": { | "repository": { | ||||
"type": "git", | "type": "git", | ||||
@@ -19,6 +19,7 @@ | |||||
"cookie": "^0.3.1", | "cookie": "^0.3.1", | ||||
"express": "^4.16.2", | "express": "^4.16.2", | ||||
"frappe-datatable": "frappe/datatable", | "frappe-datatable": "frappe/datatable", | ||||
"frappe-gantt": "^0.1.0", | |||||
"moment": "^2.20.1", | "moment": "^2.20.1", | ||||
"redis": "^2.8.0", | "redis": "^2.8.0", | ||||
"showdown": "^1.8.6", | "showdown": "^1.8.6", | ||||
@@ -28,6 +29,7 @@ | |||||
}, | }, | ||||
"devDependencies": { | "devDependencies": { | ||||
"babel-runtime": "^6.26.0", | "babel-runtime": "^6.26.0", | ||||
"chalk": "^2.3.2", | |||||
"rollup": "^0.55.3", | "rollup": "^0.55.3", | ||||
"rollup-plugin-buble": "^0.19.2", | "rollup-plugin-buble": "^0.19.2", | ||||
"rollup-plugin-commonjs": "^8.3.0", | "rollup-plugin-commonjs": "^8.3.0", | ||||
@@ -1,204 +0,0 @@ | |||||
const path = require('path'); | |||||
const fs = require('fs'); | |||||
const touch = require('touch'); | |||||
const { | |||||
get_build_json_path, | |||||
get_app_path, | |||||
apps_list, | |||||
assets_path, | |||||
get_public_path, | |||||
bench_path, | |||||
sites_path | |||||
} = require('./rollup.utils'); | |||||
const less = require('rollup-plugin-less'); | |||||
const multi_entry = require('rollup-plugin-multi-entry'); | |||||
const commonjs = require('rollup-plugin-commonjs'); | |||||
const node_resolve = require('rollup-plugin-node-resolve'); | |||||
const buble = require('rollup-plugin-buble'); | |||||
const uglify = require('rollup-plugin-uglify'); | |||||
const frappe_html = require('./frappe-html-plugin'); | |||||
const production = process.env.FRAPPE_ENV === 'production'; | |||||
ensure_js_css_dirs(); | |||||
build_libs(); | |||||
function get_app_config(app) { | |||||
const build_map = get_build_json(app); | |||||
if (!build_map) return []; | |||||
const js_config = Object.keys(build_map) | |||||
.filter(output_file => | |||||
output_file.endsWith('.js') && | |||||
// libs is built separately (to be deprecated) | |||||
!output_file.endsWith('libs.min.js') | |||||
) | |||||
.map(output_file => { | |||||
const input_files = build_map[output_file].map( | |||||
// make paths absolute | |||||
input_path => path.resolve(get_app_path(app), input_path) | |||||
); | |||||
return get_js_config(output_file, input_files); | |||||
}); | |||||
const less_config = Object.keys(build_map) | |||||
.filter(output_file => | |||||
output_file.endsWith('.css') | |||||
) | |||||
.map(output_file => { | |||||
const input_files = build_map[output_file].map( | |||||
input_path => path.resolve(get_app_path(app), input_path) | |||||
); | |||||
return get_css_config(output_file, input_files); | |||||
}); | |||||
return [].concat(js_config, less_config); | |||||
} | |||||
function get_js_config(output_file, input_files) { | |||||
const css_output_file = path.resolve(assets_path, 'css', path.basename(output_file).split('.js')[0] + '.css'); | |||||
const plugins = [ | |||||
// enables array of inputs | |||||
multi_entry(), | |||||
// .html -> .js | |||||
frappe_html(), | |||||
// less -> css | |||||
less({ | |||||
output: css_output_file, | |||||
option: { | |||||
// so that other .less files can import variables.less from frappe directly | |||||
paths: [path.resolve(get_public_path('frappe'), 'less'), path.resolve(get_app_path('frappe'), '..')], | |||||
compress: production | |||||
}, | |||||
// include: [path.resolve(bench_path, '**/*.less'), path.resolve(bench_path, '**/*.css')], | |||||
exclude: [] | |||||
}), | |||||
// ES6 -> ES5 | |||||
buble({ | |||||
objectAssign: 'Object.assign', | |||||
transforms: { | |||||
dangerousForOf: true | |||||
}, | |||||
exclude: [path.resolve(bench_path, '**/*.css'), path.resolve(bench_path, '**/*.less')] | |||||
}), | |||||
commonjs(), | |||||
node_resolve(), | |||||
production && uglify() | |||||
]; | |||||
return { | |||||
input: input_files, | |||||
plugins: plugins, | |||||
output: { | |||||
file: path.resolve(assets_path, output_file), | |||||
format: 'iife', | |||||
name: 'Rollup', | |||||
globals: { | |||||
'jquery': 'window.jQuery' | |||||
}, | |||||
sourcemap: true | |||||
}, | |||||
context: 'window', | |||||
external: ['jquery'] | |||||
}; | |||||
} | |||||
function get_css_config(output_file, input_files) { | |||||
const output_path = path.resolve(assets_path, output_file); | |||||
// clear css file to avoid appending problem | |||||
delete_file(output_path); | |||||
const plugins = [ | |||||
// enables array of inputs | |||||
multi_entry(), | |||||
// less -> css | |||||
less({ | |||||
output: output_path, | |||||
option: { | |||||
// so that other .less files can import variables.less from frappe directly | |||||
paths: [path.resolve(get_public_path('frappe'), 'less')], | |||||
compress: production | |||||
}, | |||||
include: [path.resolve(bench_path, '**/*.less'), path.resolve(bench_path, '**/*.css')] | |||||
}) | |||||
]; | |||||
return { | |||||
input: input_files, | |||||
plugins: plugins, | |||||
output: { | |||||
// this file is always empty, remove it later? | |||||
file: path.resolve(assets_path, `css/rollup.manifest.css`), | |||||
format: 'cjs', | |||||
} | |||||
}; | |||||
} | |||||
function ensure_js_css_dirs() { | |||||
const paths = [ | |||||
path.resolve(assets_path, 'js'), | |||||
path.resolve(assets_path, 'css') | |||||
]; | |||||
paths.forEach(path => { | |||||
if (!fs.existsSync(path)) { | |||||
fs.mkdirSync(path); | |||||
} | |||||
}); | |||||
// clear files in css folder | |||||
const css_path = path.resolve(assets_path, 'css'); | |||||
const files = fs.readdirSync(css_path); | |||||
files.forEach(file => { | |||||
delete_file(path.resolve(css_path, file)); | |||||
}); | |||||
} | |||||
function build_libs() { | |||||
const libs_path = 'js/libs.min.js'; | |||||
const input_files = get_build_json('frappe')[libs_path]; | |||||
const libs_content = input_files.map(file_name => { | |||||
const full_path = path.resolve(get_app_path('frappe'), file_name); | |||||
return `/* ${file_name} */\n` + fs.readFileSync(full_path); | |||||
}).join('\n\n'); | |||||
const target_path = path.resolve(assets_path, libs_path); | |||||
fs.writeFileSync(target_path, libs_content); | |||||
console.log('✨ Built libs.min.js'); // eslint-disable-line | |||||
touch(path.join(sites_path, '.build'), { force: true }); | |||||
} | |||||
function get_all_apps_config() { | |||||
let configs = []; | |||||
apps_list.forEach(app => { | |||||
configs = configs.concat(get_app_config(app)); | |||||
}); | |||||
return configs; | |||||
} | |||||
function get_build_json(app) { | |||||
try { | |||||
return require(get_build_json_path(app)); | |||||
} catch (e) { | |||||
// build.json does not exist | |||||
return null; | |||||
} | |||||
} | |||||
function delete_file(path) { | |||||
if (fs.existsSync(path)) { | |||||
fs.unlinkSync(path); | |||||
} | |||||
} | |||||
module.exports = get_all_apps_config(); |
@@ -0,0 +1,105 @@ | |||||
const fs = require('fs'); | |||||
const path = require('path'); | |||||
const chalk = require('chalk'); | |||||
const rollup = require('rollup'); | |||||
const log = console.log; // eslint-disable-line | |||||
const { | |||||
get_build_json, | |||||
get_app_path, | |||||
apps_list, | |||||
run_serially, | |||||
assets_path, | |||||
sites_path, | |||||
delete_file | |||||
} = require('./rollup.utils'); | |||||
const { | |||||
get_rollup_options | |||||
} = require('./config'); | |||||
show_production_message(); | |||||
ensure_js_css_dirs(); | |||||
build_libs(); | |||||
build_assets_for_all_apps(); | |||||
function build_assets_for_all_apps() { | |||||
run_serially( | |||||
apps_list.map(app => () => build_assets(app)) | |||||
); | |||||
} | |||||
function build_assets(app) { | |||||
const build_json = get_build_json(app); | |||||
if (!build_json) return Promise.resolve(); | |||||
log(chalk.yellow(`\nBuilding ${app} assets...\n`)); | |||||
const promises = Object.keys(build_json) | |||||
.map(output_file => { | |||||
const input_files = build_json[output_file] | |||||
.map(input_file => path.resolve(get_app_path(app), input_file)); | |||||
const { inputOptions, outputOptions } = get_rollup_options(output_file, input_files); | |||||
return build(inputOptions, outputOptions) | |||||
.then(() => { | |||||
log(`${chalk.green('✔')} Built ${output_file}`); | |||||
}); | |||||
}); | |||||
const start = Date.now(); | |||||
return Promise.all(promises) | |||||
.then(() => { | |||||
const time = Date.now() - start; | |||||
log(chalk.green(`✨ Done in ${time / 1000}s`)); | |||||
}); | |||||
} | |||||
function build(inputOptions, outputOptions) { | |||||
return rollup.rollup(inputOptions) | |||||
.then(bundle => bundle.write(outputOptions)); | |||||
} | |||||
function build_libs() { | |||||
// only concatenates lib files, not processed through rollup | |||||
const touch = require('touch'); | |||||
const libs_path = 'js/libs.min.js'; | |||||
const input_files = get_build_json('frappe')[libs_path]; | |||||
const libs_content = input_files.map(file_name => { | |||||
const full_path = path.resolve(get_app_path('frappe'), file_name); | |||||
return `/* ${file_name} */\n` + fs.readFileSync(full_path); | |||||
}).join('\n\n'); | |||||
const target_path = path.resolve(assets_path, libs_path); | |||||
fs.writeFileSync(target_path, libs_content); | |||||
log(`${chalk.green('✔')} Built ${libs_path}`); | |||||
touch(path.join(sites_path, '.build'), { force: true }); | |||||
} | |||||
function ensure_js_css_dirs() { | |||||
const paths = [ | |||||
path.resolve(assets_path, 'js'), | |||||
path.resolve(assets_path, 'css') | |||||
]; | |||||
paths.forEach(path => { | |||||
if (!fs.existsSync(path)) { | |||||
fs.mkdirSync(path); | |||||
} | |||||
}); | |||||
// clear files in css folder | |||||
const css_path = path.resolve(assets_path, 'css'); | |||||
const files = fs.readdirSync(css_path); | |||||
files.forEach(file => { | |||||
delete_file(path.resolve(css_path, file)); | |||||
}); | |||||
} | |||||
function show_production_message() { | |||||
const production = process.env.FRAPPE_ENV === 'production'; | |||||
if (production) { | |||||
log(chalk.green('Production mode')); | |||||
} | |||||
} |
@@ -0,0 +1,136 @@ | |||||
const path = require('path'); | |||||
const chalk = require('chalk'); | |||||
const log = console.log; // eslint-disable-line | |||||
const multi_entry = require('rollup-plugin-multi-entry'); | |||||
const commonjs = require('rollup-plugin-commonjs'); | |||||
const node_resolve = require('rollup-plugin-node-resolve'); | |||||
const less = require('rollup-plugin-less'); | |||||
const buble = require('rollup-plugin-buble'); | |||||
const uglify = require('rollup-plugin-uglify'); | |||||
const frappe_html = require('./frappe-html-plugin'); | |||||
const production = process.env.FRAPPE_ENV === 'production'; | |||||
const { | |||||
assets_path, | |||||
bench_path, | |||||
get_public_path, | |||||
get_app_path, | |||||
delete_file, | |||||
} = require('./rollup.utils'); | |||||
function get_rollup_options(output_file, input_files) { | |||||
if (output_file.endsWith('.js')) { | |||||
return get_rollup_options_for_js(output_file, input_files); | |||||
} else if(output_file.endsWith('.css')) { | |||||
return get_rollup_options_for_css(output_file, input_files); | |||||
} | |||||
} | |||||
function get_rollup_options_for_js(output_file, input_files) { | |||||
const css_output_file = path.resolve(assets_path, 'css', path.basename(output_file).split('.js')[0] + '.css'); | |||||
const plugins = [ | |||||
// enables array of inputs | |||||
multi_entry(), | |||||
// .html -> .js | |||||
frappe_html(), | |||||
// less -> css | |||||
less({ | |||||
output: css_output_file, | |||||
option: { | |||||
// so that other .less files can import variables.less from frappe directly | |||||
paths: [path.resolve(get_public_path('frappe'), 'less'), path.resolve(get_app_path('frappe'), '..')], | |||||
compress: production | |||||
}, | |||||
include: [path.resolve(bench_path, '**/*.less'), path.resolve(bench_path, '**/*.css')], | |||||
exclude: [] | |||||
}), | |||||
// ES6 -> ES5 | |||||
buble({ | |||||
objectAssign: 'Object.assign', | |||||
transforms: { | |||||
dangerousForOf: true | |||||
}, | |||||
exclude: [path.resolve(bench_path, '**/*.css'), path.resolve(bench_path, '**/*.less')] | |||||
}), | |||||
commonjs(), | |||||
node_resolve(), | |||||
production && uglify() | |||||
]; | |||||
return { | |||||
inputOptions: { | |||||
input: input_files, | |||||
plugins: plugins, | |||||
context: 'window', | |||||
external: ['jquery'], | |||||
onwarn({ code, message, loc, frame }) { | |||||
// skip warnings | |||||
if (['EVAL', 'SOURCEMAP_BROKEN', 'NAMESPACE_CONFLICT'].includes(code)) return; | |||||
if (loc) { | |||||
log(`${loc.file} (${loc.line}:${loc.column}) ${message}`); | |||||
if (frame) log(frame); | |||||
} else { | |||||
log(chalk.yellow.underline(code), ':', message); | |||||
} | |||||
} | |||||
}, | |||||
outputOptions: { | |||||
file: path.resolve(assets_path, output_file), | |||||
format: 'iife', | |||||
name: 'Rollup', | |||||
globals: { | |||||
'jquery': 'window.jQuery' | |||||
}, | |||||
sourcemap: true | |||||
} | |||||
}; | |||||
} | |||||
function get_rollup_options_for_css(output_file, input_files) { | |||||
const output_path = path.resolve(assets_path, output_file); | |||||
// clear css file to avoid appending problem | |||||
delete_file(output_path); | |||||
const plugins = [ | |||||
// enables array of inputs | |||||
multi_entry(), | |||||
// less -> css | |||||
less({ | |||||
output: output_path, | |||||
option: { | |||||
// so that other .less files can import variables.less from frappe directly | |||||
paths: [path.resolve(get_public_path('frappe'), 'less')], | |||||
compress: production | |||||
}, | |||||
include: [path.resolve(bench_path, '**/*.less'), path.resolve(bench_path, '**/*.css')] | |||||
}) | |||||
]; | |||||
return { | |||||
inputOptions: { | |||||
input: input_files, | |||||
plugins: plugins, | |||||
onwarn(warning) { | |||||
// skip warnings | |||||
if (['EMPTY_BUNDLE'].includes(warning.code)) return; | |||||
// console.warn everything else | |||||
log(chalk.yellow.underline(warning.code), ':', warning.message); | |||||
} | |||||
}, | |||||
outputOptions: { | |||||
// this file is always empty, remove it later? | |||||
file: path.resolve(assets_path, `css/rollup.manifest.css`), | |||||
format: 'cjs' | |||||
} | |||||
}; | |||||
} | |||||
module.exports = { | |||||
get_rollup_options | |||||
}; |
@@ -42,6 +42,31 @@ const get_public_path = app => public_paths[app]; | |||||
const get_build_json_path = app => path.resolve(get_public_path(app), 'build.json'); | const get_build_json_path = app => path.resolve(get_public_path(app), 'build.json'); | ||||
function get_build_json(app) { | |||||
try { | |||||
return require(get_build_json_path(app)); | |||||
} catch (e) { | |||||
// build.json does not exist | |||||
return null; | |||||
} | |||||
} | |||||
function delete_file(path) { | |||||
if (fs.existsSync(path)) { | |||||
fs.unlinkSync(path); | |||||
} | |||||
} | |||||
function run_serially(tasks) { | |||||
let result = Promise.resolve(); | |||||
tasks.forEach(task => { | |||||
if(task) { | |||||
result = result.then ? result.then(task) : Promise.resolve(); | |||||
} | |||||
}); | |||||
return result; | |||||
} | |||||
const get_app_path = app => app_paths[app]; | const get_app_path = app => app_paths[app]; | ||||
module.exports = { | module.exports = { | ||||
@@ -49,8 +74,11 @@ module.exports = { | |||||
bundle_map, | bundle_map, | ||||
get_public_path, | get_public_path, | ||||
get_build_json_path, | get_build_json_path, | ||||
get_build_json, | |||||
get_app_path, | get_app_path, | ||||
apps_list, | apps_list, | ||||
assets_path, | assets_path, | ||||
bench_path | |||||
bench_path, | |||||
delete_file, | |||||
run_serially | |||||
}; | }; |
@@ -0,0 +1,57 @@ | |||||
const path = require('path'); | |||||
const chalk = require('chalk'); | |||||
const rollup = require('rollup'); | |||||
const log = console.log; // eslint-disable-line | |||||
const { | |||||
apps_list, | |||||
get_app_path, | |||||
get_build_json | |||||
} = require('./rollup.utils'); | |||||
const { | |||||
get_rollup_options | |||||
} = require('./config'); | |||||
watch_assets(); | |||||
function watch_assets() { | |||||
let watchOptions = []; | |||||
apps_list.map(app => { | |||||
watchOptions.push(...get_watch_options(app)); | |||||
}); | |||||
log(chalk.green(`\nRollup Watcher Started`)); | |||||
let watcher = rollup.watch(watchOptions); | |||||
watcher.on('event', event => { | |||||
switch(event.code) { | |||||
case 'START': | |||||
log(chalk.yellow(`\nWatching...`)); | |||||
break; | |||||
case 'BUNDLE_START': | |||||
log('Rebuilding', path.basename(event.output[0])); | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
}); | |||||
} | |||||
function get_watch_options(app) { | |||||
const build_json = get_build_json(app); | |||||
if (!build_json) return []; | |||||
const watchOptions = Object.keys(build_json) | |||||
.map(output_file => { | |||||
const input_files = build_json[output_file] | |||||
.map(input_file => path.resolve(get_app_path(app), input_file)); | |||||
const { inputOptions, outputOptions } = get_rollup_options(output_file, input_files); | |||||
return Object.assign({}, inputOptions, { | |||||
output: outputOptions | |||||
}); | |||||
}).filter(Boolean); | |||||
return watchOptions; | |||||
} |
@@ -54,6 +54,12 @@ ansi-styles@^3.2.0: | |||||
dependencies: | dependencies: | ||||
color-convert "^1.9.0" | color-convert "^1.9.0" | ||||
ansi-styles@^3.2.1: | |||||
version "3.2.1" | |||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" | |||||
dependencies: | |||||
color-convert "^1.9.0" | |||||
arr-diff@^2.0.0: | arr-diff@^2.0.0: | ||||
version "2.0.0" | version "2.0.0" | ||||
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" | resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" | ||||
@@ -232,6 +238,14 @@ chalk@^2.3.1: | |||||
escape-string-regexp "^1.0.5" | escape-string-regexp "^1.0.5" | ||||
supports-color "^5.2.0" | supports-color "^5.2.0" | ||||
chalk@^2.3.2: | |||||
version "2.3.2" | |||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" | |||||
dependencies: | |||||
ansi-styles "^3.2.1" | |||||
escape-string-regexp "^1.0.5" | |||||
supports-color "^5.3.0" | |||||
cliui@^4.0.0: | cliui@^4.0.0: | ||||
version "4.0.0" | version "4.0.0" | ||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc" | resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.0.0.tgz#743d4650e05f36d1ed2575b59638d87322bfbbcc" | ||||
@@ -617,6 +631,10 @@ frappe-datatable@frappe/datatable: | |||||
clusterize.js "^0.18.0" | clusterize.js "^0.18.0" | ||||
sortablejs "^1.7.0" | sortablejs "^1.7.0" | ||||
frappe-gantt@^0.1.0: | |||||
version "0.1.0" | |||||
resolved "https://registry.yarnpkg.com/frappe-gantt/-/frappe-gantt-0.1.0.tgz#0532d7f10bc4c905ad7dd1ef8e65c7457d13355f" | |||||
fresh@0.5.2: | fresh@0.5.2: | ||||
version "0.5.2" | version "0.5.2" | ||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" | resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" | ||||
@@ -986,10 +1004,6 @@ locate-path@^2.0.0: | |||||
p-locate "^2.0.0" | p-locate "^2.0.0" | ||||
path-exists "^3.0.0" | path-exists "^3.0.0" | ||||
lodash@^4.17.5: | |||||
version "4.17.5" | |||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" | |||||
lru-cache@^4.0.1: | lru-cache@^4.0.1: | ||||
version "4.1.1" | version "4.1.1" | ||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" | ||||
@@ -1700,6 +1714,12 @@ supports-color@^5.2.0: | |||||
dependencies: | dependencies: | ||||
has-flag "^3.0.0" | has-flag "^3.0.0" | ||||
supports-color@^5.3.0: | |||||
version "5.3.0" | |||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0" | |||||
dependencies: | |||||
has-flag "^3.0.0" | |||||
to-array@0.1.4: | to-array@0.1.4: | ||||
version "0.1.4" | version "0.1.4" | ||||
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" | resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" | ||||