diff --git a/Classes/Compiler/ScssCompiler.php b/Classes/Compiler/ScssCompiler.php new file mode 100644 index 0000000..ab200d8 --- /dev/null +++ b/Classes/Compiler/ScssCompiler.php @@ -0,0 +1,87 @@ + $cacheDir, + 'prefix' => md5($cssFilename), + ]; + GeneralUtility::mkdir_deep($cacheOptions['cacheDir']); + $parser = new \ScssPhp\ScssPhp\Compiler($cacheOptions); + if (file_exists($scssFilename)) { + + $parser->setVariables($vars); + + if ($showLineNumber) { + $parser->setLineNumberStyle(\ScssPhp\ScssPhp\Compiler::LINE_COMMENTS); + } + if ($formatter !== null) { + $parser->setFormatter($formatter); + } + + if ($useSourceMap) { + $parser->setSourceMap(\ScssPhp\ScssPhp\Compiler::SOURCE_MAP_INLINE); + + $parser->setSourceMapOptions([ + 'sourceMapWriteTo' => $cssFilename . '.map', + 'sourceMapURL' => $cssRelativeFilename . '.map', + 'sourceMapBasepath' => $sitePath, + 'sourceMapRootpath' => '/', + ]); + } + + $css = $parser->compile('@import "' . $scssFilename . '";'); + GeneralUtility::writeFile($cssFilename, $css); + return $css; + } + return ''; + } + +} diff --git a/Classes/Compiler/ScssResolver.php b/Classes/Compiler/ScssResolver.php new file mode 100644 index 0000000..50fad93 --- /dev/null +++ b/Classes/Compiler/ScssResolver.php @@ -0,0 +1,206 @@ +cache = $cache; + } + + private static function calcCacheKey(string $cssRelativeFilename) { + return hash('sha1', $cssRelativeFilename); + } + + /** + * Calculating content hash to detect changes + * + * @param string $scssFilename Existing scss file absolute path + * @param string $vars + * @return string + */ + protected function calculateContentHash(string $scssFilename, string $vars = ''): string { + if (\in_array($scssFilename, self::$visitedFiles, true)) { + return ''; + } + self::$visitedFiles[] = $scssFilename; + + $content = file_get_contents($scssFilename); + $pathinfo = pathinfo($scssFilename); + + $hash = hash('sha1', $content); + if ($vars !== '') { + $hash = hash('sha1', $hash . $vars); + } // hash variables too + + $imports = self::collectImports($content); + foreach ($imports as $import) { + $hashImport = ''; + + + if (file_exists($pathinfo['dirname'] . '/' . $import . '.scss')) { + $hashImport = $this->calculateContentHash($pathinfo['dirname'] . '/' . $import . '.scss'); + } else { + $parts = explode('/', $import); + $filename = '_' . array_pop($parts); + $parts[] = $filename; + if (file_exists($pathinfo['dirname'] . '/' . implode('/', $parts) . '.scss')) { + $hashImport = $this->calculateContentHash($pathinfo['dirname'] . '/' . implode('/', + $parts) . '.scss'); + } + } + if ($hashImport !== '') { + $hash = hash('sha1', $hash . $hashImport); + } + } + + return $hash; + } + + /** + * Collect all @import files in the given content. + * + * @param string $content + * @return array + */ + private static function collectImports(string $content): array { + $matches = []; + $imports = []; + + preg_match_all('/@import([^;]*);/', $content, $matches); + + foreach ($matches[1] as $importString) { + $files = explode(',', $importString); + + array_walk($files, static function (string &$file) { + $file = trim($file, " \t\n\r\0\x0B'\""); + }); + + $imports = array_merge($imports, $files); + } + + return $imports; + } + + public function resolve(string $file, $outputDir = null, $formatter = null, array $variables = [], $showLineNumber = false, $useSourceMap = false, $outputFile = null, $inline = false): ?array { + $sitePath = Environment::getPublicPath() . '/'; + $pathInfo = pathinfo($file); + $filename = $pathInfo['filename']; + if (empty($outputDir)) { + $outputDir = self::$defaultOutputDir; + } + + if ($outputFile !== null) { + $outputDir = \dirname($outputFile); + $filename = basename($outputFile); + } + + $outputDir = (substr($outputDir, -1) === '/') ? $outputDir : $outputDir . '/'; + + if (!strcmp(substr($outputDir, 0, 4), 'EXT:')) { + [$extKey, $script] = explode('/', substr($outputDir, 4), 2); + if ($extKey && ExtensionManagementUtility::isLoaded($extKey)) { + $extPath = ExtensionManagementUtility::extPath($extKey); + $outputDir = substr($extPath, \strlen($sitePath)) . $script; + } + } + + + $scssFilename = GeneralUtility::getFileAbsFileName($file); + + // create filename - hash is important due to the possible + // conflicts with same filename in different folders + GeneralUtility::mkdir_deep($sitePath . $outputDir); + $fileEnding = (substr($filename,-4) === '.css') ? '' : '.css'; + if ($outputFile === null) { + $variablesCount = \count($variables); + $variablesHash = $variablesCount > 0 ? hash('md5', implode(',', $variables)) : null; + $variablesHashString = $variablesCount > 0 ? '_' . $variablesHash : ''; + $fileNameOutputString = ($outputDir === self::$defaultOutputDir) ? '_' . hash('sha1', $file) : $variablesHashString; + + $cssRelativeFilename = $outputDir . $filename . $fileNameOutputString . $fileEnding; + } else { + $cssRelativeFilename = $outputDir . $filename . $fileEnding; + } + + + $cssFilename = $sitePath . $cssRelativeFilename; + + $cacheKey = self::calcCacheKey($cssRelativeFilename); + $contentHash = $this->calculateContentHash($scssFilename, implode(',', $variables)); + if ($showLineNumber) { + $contentHash .= 'l1'; + } + if ($useSourceMap) { + $contentHash .= 'sm'; + } + $contentHash .= $formatter; + + $contentHashCache = ''; + if ($this->cache->has($cacheKey)) { + $contentHashCache = $this->cache->get($cacheKey); + } + + + $css = $this->compile($scssFilename, $cssFilename, $contentHashCache, $contentHash, $cacheKey, $variables, $showLineNumber, $formatter, $cssRelativeFilename, $useSourceMap); + // error + if ($css === null) { + return null; + } + if ($inline) { + if ($css === '') { + $css = file_get_contents($cssFilename); + } + return [$cssRelativeFilename, $css]; + } + return [$cssRelativeFilename, null]; + } + + private function compile(string $scssFilename, + string $cssFilename, + string $contentHashCache, + string $contentHash, + string $cacheKey, + array $variables = [], + bool $showLineNumber = false, + $formatter = null, + $cssRelativeFilename = null, + bool $useSourceMap = false): ?string { + $css = ''; + + try { + if ($contentHashCache === '' || $contentHashCache !== $contentHash) { + $css = ScssCompiler::compileScss($scssFilename, $cssFilename, $variables, $showLineNumber, $formatter, $cssRelativeFilename, $useSourceMap); + + $this->cache->set($cacheKey, $contentHash, ['scss'], 0); + } + return $css; + } catch (\Exception $ex) { + DebugUtility::debug($ex->getMessage()); + + /** @var $logger Logger */ + $logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); + $logger->error($ex->getMessage()); + } + return null; + } + +} diff --git a/Classes/EventListener/CompileScssAssets.php b/Classes/EventListener/CompileScssAssets.php new file mode 100644 index 0000000..e93a1b7 --- /dev/null +++ b/Classes/EventListener/CompileScssAssets.php @@ -0,0 +1,44 @@ +isInline()) { + return; + } + $assetCollector = $event->getAssetCollector(); + $assets = $assetCollector->getStyleSheets($event->isPriority()); + + foreach ($assets as $identifier => $asset) { + if (!empty($asset['source'])) { + $pathInfo = pathinfo($asset['source']); + if ($pathInfo['extension'] === 'scss') { + $assetCollector->removeStyleSheet($identifier); + /** @var ScssResolver $scssResolver */ + $scssResolver = GeneralUtility::makeInstance(ScssResolver::class); + $resolved = $scssResolver->resolve( + $asset['source'], + null, + 'WapplerSystems\WsScss\Formatter\Autoprefixer', + [], + false, + false, + null, + false); + if ($resolved === null) { + // error remove + return; + } + $assetCollector->addStyleSheet($identifier, $resolved[0], $asset['attributes'], $asset['options']); + } + } + } + } +} diff --git a/Classes/Hooks/RenderPreProcessorHook.php b/Classes/Hooks/RenderPreProcessorHook.php index 83b1f70..d9208a7 100644 --- a/Classes/Hooks/RenderPreProcessorHook.php +++ b/Classes/Hooks/RenderPreProcessorHook.php @@ -22,15 +22,10 @@ * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ -use TYPO3\CMS\Core\Cache\Backend\FileBackend; -use TYPO3\CMS\Core\Cache\CacheManager; -use TYPO3\CMS\Core\Log\Logger; use TYPO3\CMS\Core\Page\PageRenderer; -use TYPO3\CMS\Core\Utility\DebugUtility; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; -use TYPO3\CMS\Core\Log\LogManager; use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer; +use WapplerSystems\WsScss\Compiler\ScssResolver; /** * Hook to preprocess scss files @@ -42,9 +37,7 @@ class RenderPreProcessorHook { - private static $visitedFiles = []; - private $variables = []; /** * @var \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer @@ -70,8 +63,7 @@ public function renderPreProcessorProc(&$params, PageRenderer $pagerenderer) } $defaultOutputDir = 'typo3temp/assets/css/'; - - $sitePath = \TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/'; + $variables = []; $setup = $GLOBALS['TSFE']->tmpl->setup; if (\is_array($setup['plugin.']['tx_wsscss.']['variables.'])) { @@ -94,8 +86,6 @@ public function renderPreProcessorProc(&$params, PageRenderer $pagerenderer) $this->variables = $parsedTypoScriptVariables; } - $variablesHash = \count($this->variables) > 0 ? hash('md5', implode(',', $this->variables)) : null; - $filePathSanitizer = GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Resource\FilePathSanitizer::class); // we need to rebuild the CSS array to keep order of CSS files @@ -111,7 +101,6 @@ public function renderPreProcessorProc(&$params, PageRenderer $pagerenderer) $outputDir = $defaultOutputDir; $inlineOutput = false; - $filename = $pathInfo['filename']; $formatter = null; $showLineNumber = false; $useSourceMap = false; @@ -139,78 +128,24 @@ public function renderPreProcessorProc(&$params, PageRenderer $pagerenderer) } } } - if ($outputFile !== null) { - $outputDir = \dirname($outputFile); - $filename = basename($outputFile); - } - - $outputDir = (substr($outputDir, -1) === '/') ? $outputDir : $outputDir . '/'; - - if (!strcmp(substr($outputDir, 0, 4), 'EXT:')) { - [$extKey, $script] = explode('/', substr($outputDir, 4), 2); - if ($extKey && ExtensionManagementUtility::isLoaded($extKey)) { - $extPath = ExtensionManagementUtility::extPath($extKey); - $outputDir = substr($extPath, \strlen($sitePath)) . $script; - } - } - - - $scssFilename = GeneralUtility::getFileAbsFileName($conf['file']); - - // create filename - hash is important due to the possible - // conflicts with same filename in different folders - GeneralUtility::mkdir_deep($sitePath . $outputDir); - if ($outputFile === null) { - $cssRelativeFilename = $outputDir . $filename . (($outputDir === $defaultOutputDir) ? '_' . hash('sha1', - $file) : (\count($this->variables) > 0 ? '_' . $variablesHash : '')) . ((substr($filename,-4) === '.css') ? '' : '.css'); - } else { - $cssRelativeFilename = $outputDir . $filename . ((substr($filename,-4) === '.css') ? '' : '.css'); - } - $cssFilename = $sitePath . $cssRelativeFilename; - - /** @var FileBackend $cache */ - $cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('ws_scss'); - $cacheKey = hash('sha1', $cssRelativeFilename); - $contentHash = $this->calculateContentHash($scssFilename, implode(',', $this->variables)); - if ($showLineNumber) { - $contentHash .= 'l1'; - } - if ($useSourceMap) { - $contentHash .= 'sm'; - } - $contentHash .= $formatter; + /** @var ScssResolver $scssResolver */ + $scssResolver = GeneralUtility::makeInstance(ScssResolver::class); + $resolved = $scssResolver->resolve($conf['file'], $outputDir, $formatter, $variables, $showLineNumber, $useSourceMap, $outputFile, $inlineOutput); - $contentHashCache = ''; - if ($cache->has($cacheKey)) { - $contentHashCache = $cache->get($cacheKey); + if ($resolved === null) { + // error in compiling + // TODO unset all } - $css = ''; + $cssRelativeFilename = $resolved[0]; - try { - if ($contentHashCache === '' || $contentHashCache !== $contentHash) { - $css = $this->compileScss($scssFilename, $cssFilename, $this->variables, $showLineNumber, $formatter, $cssRelativeFilename, $useSourceMap); - - $cache->set($cacheKey, $contentHash, ['scss'], 0); - } - } catch (\Exception $ex) { - DebugUtility::debug($ex->getMessage()); - - /** @var $logger Logger */ - $logger = GeneralUtility::makeInstance(LogManager::class)->getLogger(__CLASS__); - $logger->error($ex->getMessage()); - } if ($inlineOutput) { unset($cssFiles[$cssRelativeFilename]); - if ($css === '') { - $css = file_get_contents($cssFilename); - } - // TODO: compression $params['cssInline'][$cssRelativeFilename] = [ - 'code' => $css, + 'code' => $cssRelativeFilename[1], ]; } else { $cssFiles[$cssRelativeFilename] = $params['cssFiles'][$file]; @@ -221,146 +156,4 @@ public function renderPreProcessorProc(&$params, PageRenderer $pagerenderer) } $params['cssFiles'] = $cssFiles; } - - /** - * Compiling Scss with scss - * - * @param string $scssFilename Existing scss file absolute path - * @param string $cssFilename File to be written with compiled CSS - * @param array $vars Variables to compile - * @param boolean $showLineNumber Show line numbers - * @param string $formatter name - * @param string $cssRelativeFilename - * @param boolean $useSourceMap Use SourceMap - * @return string - * @throws \BadFunctionCallException - */ - protected function compileScss($scssFilename, $cssFilename, $vars = [], $showLineNumber = false, $formatter = null, $cssRelativeFilename = null, $useSourceMap = false): string - { - - $sitePath = \TYPO3\CMS\Core\Core\Environment::getPublicPath() . '/'; - if (!class_exists(\ScssPhp\ScssPhp\Version::class, true)) { - $extPath = ExtensionManagementUtility::extPath('ws_scss'); - require_once $extPath . 'Resources/Private/scssphp/scss.inc.php'; - } - - $cacheDir = $sitePath . 'typo3temp/assets/css/cache/'; - - if (!is_dir($cacheDir)) { - GeneralUtility::mkdir_deep($cacheDir); - } - - if (!is_writable($cacheDir)) { - // TODO: Error message - return ''; - } - - $cacheOptions = [ - 'cacheDir' => $cacheDir, - 'prefix' => md5($cssFilename), - ]; - $parser = new \ScssPhp\ScssPhp\Compiler($cacheOptions); - if (file_exists($scssFilename)) { - - $parser->setVariables($vars); - - if ($showLineNumber) { - $parser->setLineNumberStyle(\ScssPhp\ScssPhp\Compiler::LINE_COMMENTS); - } - if ($formatter !== null) { - $parser->setFormatter($formatter); - } - - if ($useSourceMap) { - $parser->setSourceMap(\ScssPhp\ScssPhp\Compiler::SOURCE_MAP_INLINE); - - $parser->setSourceMapOptions([ - 'sourceMapWriteTo' => $cssFilename . '.map', - 'sourceMapURL' => $cssRelativeFilename . '.map', - 'sourceMapBasepath' => $sitePath, - 'sourceMapRootpath' => '/', - ]); - } - - $css = $parser->compile('@import "' . $scssFilename . '";'); - - GeneralUtility::writeFile($cssFilename, $css); - - return $css; - } - - return ''; - } - - /** - * Calculating content hash to detect changes - * - * @param string $scssFilename Existing scss file absolute path - * @param string $vars - * @return string - */ - protected function calculateContentHash($scssFilename, $vars = ''): string - { - if (\in_array($scssFilename, self::$visitedFiles, true)) { - return ''; - } - self::$visitedFiles[] = $scssFilename; - - $content = file_get_contents($scssFilename); - $pathinfo = pathinfo($scssFilename); - - $hash = hash('sha1', $content); - if ($vars !== '') { - $hash = hash('sha1', $hash . $vars); - } // hash variables too - - $imports = $this->collectImports($content); - foreach ($imports as $import) { - $hashImport = ''; - - - if (file_exists($pathinfo['dirname'] . '/' . $import . '.scss')) { - $hashImport = $this->calculateContentHash($pathinfo['dirname'] . '/' . $import . '.scss'); - } else { - $parts = explode('/', $import); - $filename = '_' . array_pop($parts); - $parts[] = $filename; - if (file_exists($pathinfo['dirname'] . '/' . implode('/', $parts) . '.scss')) { - $hashImport = $this->calculateContentHash($pathinfo['dirname'] . '/' . implode('/', - $parts) . '.scss'); - } - } - if ($hashImport !== '') { - $hash = hash('sha1', $hash . $hashImport); - } - } - - return $hash; - } - - /** - * Collect all @import files in the given content. - * - * @param string $content - * @return array - */ - protected function collectImports(string $content): array - { - $matches = []; - $imports = []; - - preg_match_all('/@import([^;]*);/', $content, $matches); - - foreach ($matches[1] as $importString) { - $files = explode(',', $importString); - - array_walk($files, function(string &$file) { - $file = trim($file, " \t\n\r\0\x0B'\""); - }); - - $imports = array_merge($imports, $files); - } - - return $imports; - } } diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml new file mode 100644 index 0000000..914c12c --- /dev/null +++ b/Configuration/Services.yaml @@ -0,0 +1,23 @@ +services: + cache.ws_scss: + class: TYPO3\CMS\Core\Cache\Frontend\FrontendInterface + factory: [ '@TYPO3\CMS\Core\Cache\CacheManager', 'getCache' ] + arguments: [ 'ws_scss' ] + + _defaults: + autowire: true + autoconfigure: true + public: true + + WapplerSystems\WsScss\: + resource: '../Classes/*' + + WapplerSystems\WsScss\EventListener\CompileScssAssets: + tags: + - name: event.listener + identifier: 'ws-sass/compileScssListener' + event: TYPO3\CMS\Core\Page\Event\BeforeStylesheetsRenderingEvent + + WapplerSystems\WsScss\Compiler\ScssResolver: + arguments: + $cache: '@cache.ws_scss' diff --git a/Resources/Private/csscrush/.eslintrc.js b/Resources/Private/csscrush/.eslintrc.js new file mode 100644 index 0000000..d9ee412 --- /dev/null +++ b/Resources/Private/csscrush/.eslintrc.js @@ -0,0 +1,107 @@ +/*eslint sort-keys: 2*/ +/*eslint object-property-newline: 2*/ +/*eslint quote-props: [2, "consistent"]*/ + +module.exports = { + env: { + es6: true, + node: true, + }, + extends: 'eslint:recommended', + parserOptions: { + ecmaVersion: 9, + }, + rules: { + 'array-bracket-spacing': [2, 'never'], + 'array-element-newline': [2, 'consistent'], + 'arrow-parens': [2, 'as-needed'], + 'arrow-spacing': 2, + 'brace-style': [2, 'stroustrup'], + 'camelcase': [2, { + ignoreDestructuring: true, + properties: 'never', + }], + 'comma-dangle': [2, { + arrays: 'always-multiline', + functions: 'never', + objects: 'always-multiline', + }], + 'comma-spacing': [2, { + after: true, + before: false, + }], + 'curly': 2, + 'eol-last': [2, 'always'], + 'eqeqeq': 2, + 'key-spacing': [2, { + afterColon: true, + beforeColon: false, + }], + 'keyword-spacing': 2, + 'linebreak-style': [2, 'unix'], + 'multiline-comment-style': [2, 'starred-block'], + 'no-console': 2, + 'no-dupe-keys': 2, + 'no-else-return': 2, + 'no-empty': [2, { + allowEmptyCatch: true, + }], + 'no-lonely-if': 2, + 'no-multi-spaces': 2, + 'no-multiple-empty-lines': [2, { + max: 2, + maxBOF: 1, + maxEOF: 1, + }], + 'no-new-object': 2, + 'no-template-curly-in-string': 2, + 'no-tabs': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': 2, + 'no-unneeded-ternary': 2, + 'no-unused-expressions': [2, {allowShortCircuit: true}], + 'no-unused-vars': [2, { + args: 'all', + argsIgnorePattern: '^(req|res|next)$|^_', + varsIgnorePattern: '^_$', + }], + 'no-useless-call': 2, + 'no-useless-concat': 2, + 'no-useless-return': 2, + 'no-var': 2, + 'object-curly-newline': [2, {consistent: true}], + 'object-curly-spacing': [2, 'never'], + 'object-shorthand': [2, 'properties'], + 'operator-linebreak': [2, 'before', { + overrides: { + ':': 'ignore', + '?': 'ignore', + }, + }], + 'prefer-arrow-callback': 2, + 'prefer-const': [2, {destructuring: 'all'}], + 'prefer-destructuring': [2, { + array: false, + object: true, + }], + 'prefer-object-spread': 2, + 'quote-props': [2, 'as-needed'], + 'quotes': [2, 'single', { + allowTemplateLiterals: true, + avoidEscape: true, + }], + 'semi': [2, 'always'], + 'space-before-blocks': 2, + 'space-before-function-paren': [2, { + anonymous: 'always', + asyncArrow: 'always', + named: 'never', + }], + 'space-unary-ops': [2, { + nonwords: false, + overrides: {'!': true}, + words: true, + }], + 'yoda': 2, + }, +}; diff --git a/Resources/Private/csscrush/composer.json b/Resources/Private/csscrush/composer.json new file mode 100644 index 0000000..10cee4b --- /dev/null +++ b/Resources/Private/csscrush/composer.json @@ -0,0 +1,33 @@ +{ + "name": "css-crush/css-crush", + "type": "library", + "description": "CSS preprocessor", + "keywords": ["css", "preprocessor"], + "homepage": "http://the-echoplex.net/csscrush", + "license": "MIT", + "authors": [ + { + "name": "Pete Boere", + "email": "pete@the-echoplex.net" + }, + { + "name": "GitHub contributors", + "homepage": "https://github.com/peteboere/css-crush/contributors" + } + ], + "require": { + "php": ">=5.6.1" + }, + "require-dev": { + "phpunit/phpunit": "5.*", + "psr/log": "1.0.*@dev", + "twig/twig": "1.*" + }, + "bin": [ + "bin/csscrush" + ], + "autoload": { + "psr-0": { "CssCrush": "lib/" }, + "files": [ "lib/functions.php" ] + } +} diff --git a/Resources/Private/csscrush/index.js b/Resources/Private/csscrush/index.js new file mode 100644 index 0000000..925f6c5 --- /dev/null +++ b/Resources/Private/csscrush/index.js @@ -0,0 +1,153 @@ +/*eslint no-control-regex: 0*/ + +const path = require('path'); +const querystring = require('querystring'); +const {EventEmitter} = require('events'); +const cliPath = path.resolve(__dirname, './cli.php'); + +const processes = []; +const processExec = (...args) => { + processes.push(require('child_process').exec(...args)); + return processes[processes.length-1]; +}; + +process.on('exit', () => { + processes.filter(it => it).forEach(proc => proc.kill()); +}); + +const self = module.exports = {}; + +class Process extends EventEmitter { + + exec(options) { + return new Promise(resolve => { + let command = this.assembleCommand(options); + const {stdIn} = options; + if (stdIn) { + command = `echo '${stdIn.replace(/'/g, "\\'")}' | ${command}`; + } + processExec(command, (error, stdout, stderr) => { + process.stderr.write(stderr.toString()); + if (error) { + return resolve(false); + } + const stdOut = stdout.toString(); + if (stdIn) { + process.stdout.write(stdOut); + } + return resolve(stdOut || true); + }); + }); + } + + watch(options) { + options.watch = true; + const command = this.assembleCommand(options); + const proc = processExec(command); + + /* + * Emitting 'error' events from EventEmitter without + * any error listener will throw uncaught exception. + */ + this.on('error', () => {}); + + proc.stderr.on('data', msg => { + msg = msg.toString(); + process.stderr.write(msg); + msg = msg.replace(/\x1B\[[^m]*m/g, '').trim(); + + const [, signal, detail] = /^([A-Z]+):\s*(.+)/i.exec(msg) || []; + const {input, output} = options; + const eventData = { + signal, + options: { + input: input ? path.resolve(input) : null, + output: output ? path.resolve(output) : null, + }, + }; + + if (/^(WARNING|ERROR)$/.test(signal)) { + const error = new Error(detail); + Object.assign(error, eventData, {severity: signal.toLowerCase()}); + this.emit('error', error); + } + else { + this.emit('data', {message: detail, ...eventData}); + } + }); + return this; + } + + assembleCommand(options) { + return `${self.phpBin || 'php'} ${cliPath} ${this.stringifyOptions(options)}`; + } + + stringifyOptions(options) { + const args = []; + options = {...options}; + for (let name in options) { + // Normalize to hypenated case. + const cssCase = name.replace(/[A-Z]/g, m => `-${m.toLowerCase()}`); + if (name !== cssCase) { + options[cssCase] = options[name]; + delete options[name]; + name = cssCase; + } + let value = options[name]; + switch (name) { + // Booleans. + case 'watch': // fallthrough + case 'source-map': // fallthrough + case 'boilerplate': // fallthrough + if (value) { + args.push(`--${name}`); + } + break; + case 'minify': + if (! value) { + args.push(`--pretty`); + } + break; + // Array/list values. + case 'vendor-target': // fallthrough + case 'plugins': // fallthrough + case 'import-path': + if (value) { + value = (Array.isArray(value) ? value : [value]).join(','); + args.push(`--${name}="${value}"`); + } + break; + // String values. + case 'newlines': // fallthrough + case 'formatter': // fallthrough + case 'input': // fallthrough + case 'context': // fallthrough + case 'output': + if (value) { + args.push(`--${name}="${value}"`); + } + break; + case 'vars': + args.push(`--${name}="${querystring.stringify(value)}"`); + break; + } + } + + return args.join(' '); + } +} + +self.watch = (file, options={}) => { + options.input = file; + return (new Process()).watch(options); +}; + +self.file = (file, options={}) => { + options.input = file; + return (new Process()).exec(options); +}; + +self.string = (string, options={}) => { + options.stdIn = string; + return (new Process()).exec(options); +}; diff --git a/Resources/Private/csscrush/package-lock.json b/Resources/Private/csscrush/package-lock.json new file mode 100644 index 0000000..2df0a7b --- /dev/null +++ b/Resources/Private/csscrush/package-lock.json @@ -0,0 +1,988 @@ +{ + "name": "csscrush", + "version": "3.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", + "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "dev": true + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.5.1.tgz", + "integrity": "sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.2", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.1", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "espree": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", + "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "dev": true, + "requires": { + "acorn": "^7.1.0", + "acorn-jsx": "^5.1.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", + "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", + "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "normalize.css": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-7.0.0.tgz", + "integrity": "sha1-q/sd2CRwZ04DIrU86xqvQSk45L8=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rxjs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", + "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + } + } +} diff --git a/Resources/Private/csscrush/package.json b/Resources/Private/csscrush/package.json new file mode 100644 index 0000000..2c38578 --- /dev/null +++ b/Resources/Private/csscrush/package.json @@ -0,0 +1,24 @@ +{ + "name": "csscrush", + "version": "3.0.1", + "description": "CSS-Crush, CSS preprocessor", + "repository": { + "type": "git", + "url": "https://github.com/peteboere/css-crush.git" + }, + "bugs": { + "url": "https://github.com/peteboere/css-crush/issues" + }, + "bin": { + "csscrush": "./bin/csscrush" + }, + "scripts": { + "lint": "eslint --fix index.js" + }, + "homepage": "http://the-echoplex.net/csscrush", + "license": "MIT", + "devDependencies": { + "eslint": "~6.5.1", + "normalize.css": "7.0.0" + } +} diff --git a/Resources/Private/scssphp/README.md b/Resources/Private/scssphp/README.md index 86eba25..5455734 100644 --- a/Resources/Private/scssphp/README.md +++ b/Resources/Private/scssphp/README.md @@ -1,12 +1,12 @@ # scssphp -### +### -[![Build](https://travis-ci.org/scssphp/scssphp.svg?branch=master)](http://travis-ci.org/scssphp/scssphp) +![Build](https://github.com/scssphp/scssphp/workflows/CI/badge.svg) [![License](https://poser.pugx.org/scssphp/scssphp/license)](https://packagist.org/packages/scssphp/scssphp) `scssphp` is a compiler for SCSS written in PHP. -Checkout the homepage, , for directions on how to use. +Checkout the homepage, , for directions on how to use. ## Running Tests @@ -23,7 +23,7 @@ There are several tests in the `tests/` directory: * `FailingTest.php` contains tests reported in Github issues that demonstrate compatibility bugs. * `InputTest.php` compiles every `.scss` file in the `tests/inputs` directory then compares to the respective `.css` file in the `tests/outputs` directory. -* `ScssTest.php` extracts (ruby) `scss` tests from the `tests/scss_test.rb` file. +* `SassSpecTest.php` extracts tests from the `sass/sass-spec` repository. When changing any of the tests in `tests/inputs`, the tests will most likely fail because the output has changed. Once you verify that the output is correct @@ -31,16 +31,17 @@ you can run the following command to rebuild all the tests: BUILD=1 vendor/bin/phpunit tests -This will compile all the tests, and save results into `tests/outputs`. +This will compile all the tests, and save results into `tests/outputs`. It also +updates the list of excluded specs from sass-spec. -To enable the `scss` compatibility tests: +To enable the full `sass-spec` compatibility tests: - TEST_SCSS_COMPAT=1 vendor/bin/phpunit tests + TEST_SASS_SPEC=1 vendor/bin/phpunit tests ## Coding Standard -`scssphp` source conforms to [PSR2](http://www.php-fig.org/psr/psr-2/). +`scssphp` source conforms to [PSR12](https://www.php-fig.org/psr/psr-12/). Run the following command from the root directory to check the code for "sniffs". - vendor/bin/phpcs --standard=PSR2 bin src tests + vendor/bin/phpcs --standard=PSR12 --extensions=php bin src tests *.php diff --git a/Resources/Private/scssphp/bin/pscss b/Resources/Private/scssphp/bin/pscss new file mode 100644 index 0000000..8b2e466 --- /dev/null +++ b/Resources/Private/scssphp/bin/pscss @@ -0,0 +1,200 @@ +#!/usr/bin/env php +parse($data)), true)); + + exit(); +} + +$scss = new Compiler(); + +if ($loadPaths) { + $scss->setImportPaths(explode(PATH_SEPARATOR, $loadPaths)); +} + +if ($style) { + if ($style === OutputStyle::COMPRESSED || $style === OutputStyle::EXPANDED) { + $scss->setOutputStyle($style); + } else { + fwrite(STDERR, "WARNING: the $style style is deprecated.\n"); + $scss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\' . ucfirst($style)); + } +} + +if ($sourceMap) { + $scss->setSourceMap(Compiler::SOURCE_MAP_INLINE); +} + +if ($encoding) { + $scss->setEncoding($encoding); +} + +try { + echo $scss->compile($data, $inputFile); +} catch (SassException $e) { + fwrite(STDERR, $e->getMessage()."\n"); + exit(1); +} diff --git a/Resources/Private/scssphp/composer.json b/Resources/Private/scssphp/composer.json new file mode 100644 index 0000000..e4c47d3 --- /dev/null +++ b/Resources/Private/scssphp/composer.json @@ -0,0 +1,65 @@ +{ + "name": "scssphp/scssphp", + "type": "library", + "description": "scssphp is a compiler for SCSS written in PHP.", + "keywords": ["css", "stylesheet", "scss", "sass", "less"], + "homepage": "http://scssphp.github.io/scssphp/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthon Pang", + "email": "apang@softwaredevelopment.ca", + "homepage": "https://github.com/robocoder" + }, + { + "name": "Cédric Morin", + "email": "cedric@yterium.com", + "homepage": "https://github.com/Cerdic" + } + ], + "autoload": { + "psr-4": { "ScssPhp\\ScssPhp\\": "src/" } + }, + "autoload-dev": { + "psr-4": { "ScssPhp\\ScssPhp\\Tests\\": "tests/" } + }, + "require": { + "php": ">=5.6.0", + "ext-json": "*", + "ext-ctype": "*" + }, + "require-dev": { + "phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.3 || ^9.4", + "sass/sass-spec": "2020.12.29", + "squizlabs/php_codesniffer": "~3.5", + "symfony/phpunit-bridge": "^5.1", + "twbs/bootstrap": "~4.3", + "zurb/foundation": "~6.5" + }, + "repositories": [ + { + "type": "package", + "package": { + "name": "sass/sass-spec", + "version": "2020.12.29", + "source": { + "type": "git", + "url": "https://github.com/sass/sass-spec.git", + "reference": "d975d33146fb679a6b359ceca329012f02e4a794" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sass/sass-spec/zipball/d975d33146fb679a6b359ceca329012f02e4a794", + "reference": "d975d33146fb679a6b359ceca329012f02e4a794", + "shasum": "" + } + } + } + ], + "bin": ["bin/pscss"], + "config": { + "sort-packages": true + } +} diff --git a/Resources/Private/scssphp/phpcs.xml.dist b/Resources/Private/scssphp/phpcs.xml.dist new file mode 100644 index 0000000..b162dbd --- /dev/null +++ b/Resources/Private/scssphp/phpcs.xml.dist @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/Resources/Public/Icons/Extension.svg b/Resources/Public/Icons/Extension.svg new file mode 100644 index 0000000..f94d7d7 --- /dev/null +++ b/Resources/Public/Icons/Extension.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/composer.json b/composer.json index f4ccd9b..8911332 100644 --- a/composer.json +++ b/composer.json @@ -11,8 +11,8 @@ "sass" ], "require": { - "typo3/cms-core": "^9.5 || ^10.4 || ^11", - "php": "^7.2", + "typo3/cms-core": "^10.4 || ^11", + "php": "^7.4", "scssphp/scssphp": "^1", "css-crush/css-crush": "^3" }, diff --git a/ext_emconf.php b/ext_emconf.php index 0cf22a6..ee25f5c 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -14,34 +14,26 @@ 'title' => 'SASS compiler for TYPO3', 'description' => 'Compiles scss files to CSS files.', 'category' => 'fe', - 'shy' => 0, - 'version' => '1.1.24', - 'dependencies' => '', - 'conflicts' => '', - 'priority' => '', - 'loadOrder' => '', - 'module' => '', - 'state' => 'stable', - 'uploadfolder' => 0, - 'createDirs' => '', - 'modify_tables' => '', - 'clearcacheonload' => 0, - 'lockType' => '', 'author' => 'Sven Wappler', 'author_email' => 'typo3YYYY@wappler.systems', 'author_company' => 'WapplerSystems', - 'CGLcompliance' => '', - 'CGLcompliance_note' => '', + 'version' => '1.2.0', + 'state' => 'alpha', + 'clearCacheOnLoad' => false, 'constraints' => [ 'depends' => [ - 'php' => '7.2.0-7.4.99', - 'typo3' => '9.5.0-11.1.99', + 'php' => '7.4.0-7.4.99', + 'typo3' => '10.4.0-11.1.99', ], 'conflicts' => [ ], 'suggests' => [ ], ], - 'suggests' => [ - ], + 'autoload' => [ + 'psr-4' => [ + 'WapplerSystems\\WsScss\\' => 'Classes', + 'ScssPhp\\ScssPhp\\' => 'Resources/Private/scssphp/src/' + ] + ] ]; diff --git a/ext_icon.png b/ext_icon.png deleted file mode 100644 index 911e9b7..0000000 Binary files a/ext_icon.png and /dev/null differ diff --git a/ext_localconf.php b/ext_localconf.php index fea7ad7..c54c8b9 100644 --- a/ext_localconf.php +++ b/ext_localconf.php @@ -1,20 +1,22 @@ renderPreProcessorProc'; } -// Caching the pages - default expire 3600 seconds -if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss']) - && !is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss'])) { - $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss'] = [ - 'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class, - 'backend' => \TYPO3\CMS\Core\Cache\Backend\FileBackend::class, - 'options' => [ - 'defaultLifetime' => 0, - ] + +if (!is_array($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss'])) { + $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss'] = []; +} +if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss']['backend'])) { + $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss']['backend'] = \TYPO3\CMS\Core\Cache\Backend\FileBackend::class; +} +if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss']['frontend'])) { + $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss']['frontend'] = \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class; +} +if (!isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss']['options'])) { + $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['ws_scss']['options'] = [ + 'defaultLifetime' => 0, ]; } diff --git a/ext_typoscript_setup.txt b/ext_typoscript_setup.txt deleted file mode 100644 index 6bc83f5..0000000 --- a/ext_typoscript_setup.txt +++ /dev/null @@ -1,9 +0,0 @@ - -plugin.tx_wsscss.variables { - - - - #test = #666 - - -}