Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / consolidation / robo / src / Task / Assets / Minify.php
diff --git a/vendor/consolidation/robo/src/Task/Assets/Minify.php b/vendor/consolidation/robo/src/Task/Assets/Minify.php
new file mode 100644 (file)
index 0000000..3187714
--- /dev/null
@@ -0,0 +1,297 @@
+<?php
+namespace Robo\Task\Assets;
+
+use Robo\Result;
+use Robo\Task\BaseTask;
+
+/**
+ * Minifies asset file (CSS or JS).
+ *
+ * ``` php
+ * <?php
+ * $this->taskMinify( 'web/assets/theme.css' )
+ *      ->run()
+ * ?>
+ * ```
+ * Please install additional dependencies to use:
+ *
+ * ```
+ * "patchwork/jsqueeze": "~1.0",
+ * "natxet/CssMin": "~3.0"
+ * ```
+ */
+class Minify extends BaseTask
+{
+    /**
+     * @var array
+     */
+    protected $types = ['css', 'js'];
+
+    /**
+     * @var string
+     */
+    protected $text;
+
+    /**
+     * @var string
+     */
+    protected $dst;
+
+    /**
+     * @var string
+     */
+    protected $type;
+
+    /**
+     * @var array
+     */
+    protected $squeezeOptions = [
+        'singleLine' => true,
+        'keepImportantComments' => true,
+        'specialVarRx' => false,
+    ];
+
+    /**
+     * Constructor. Accepts asset file path or string source.
+     *
+     * @param string $input
+     */
+    public function __construct($input)
+    {
+        if (file_exists($input)) {
+            $this->fromFile($input);
+            return;
+        }
+
+        $this->fromText($input);
+    }
+
+    /**
+     * Sets destination. Tries to guess type from it.
+     *
+     * @param string $dst
+     *
+     * @return $this
+     */
+    public function to($dst)
+    {
+        $this->dst = $dst;
+
+        if (!empty($this->dst) && empty($this->type)) {
+            $this->type($this->getExtension($this->dst));
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets type with validation.
+     *
+     * @param string $type css|js
+     *
+     * @return $this
+     */
+    public function type($type)
+    {
+        $type = strtolower($type);
+
+        if (in_array($type, $this->types)) {
+            $this->type = $type;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Sets text from string source.
+     *
+     * @param string $text
+     *
+     * @return $this
+     */
+    protected function fromText($text)
+    {
+        $this->text = (string)$text;
+        unset($this->type);
+
+        return $this;
+    }
+
+    /**
+     * Sets text from asset file path. Tries to guess type and set default destination.
+     *
+     * @param string $path
+     *
+     * @return $this
+     */
+    protected function fromFile($path)
+    {
+        $this->text = file_get_contents($path);
+
+        unset($this->type);
+        $this->type($this->getExtension($path));
+
+        if (empty($this->dst) && !empty($this->type)) {
+            $ext_length = strlen($this->type) + 1;
+            $this->dst = substr($path, 0, -$ext_length) . '.min.' . $this->type;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Gets file extension from path.
+     *
+     * @param string $path
+     *
+     * @return string
+     */
+    protected function getExtension($path)
+    {
+        return pathinfo($path, PATHINFO_EXTENSION);
+    }
+
+    /**
+     * Minifies and returns text.
+     *
+     * @return string|bool
+     */
+    protected function getMinifiedText()
+    {
+        switch ($this->type) {
+            case 'css':
+                if (!class_exists('\CssMin')) {
+                    return Result::errorMissingPackage($this, 'CssMin', 'natxet/CssMin');
+                }
+
+                return \CssMin::minify($this->text);
+                break;
+
+            case 'js':
+                if (!class_exists('\JSqueeze') && !class_exists('\Patchwork\JSqueeze')) {
+                    return Result::errorMissingPackage($this, 'Patchwork\JSqueeze', 'patchwork/jsqueeze');
+                }
+
+                if (class_exists('\JSqueeze')) {
+                    $jsqueeze = new \JSqueeze();
+                } else {
+                    $jsqueeze = new \Patchwork\JSqueeze();
+                }
+
+                return $jsqueeze->squeeze(
+                    $this->text,
+                    $this->squeezeOptions['singleLine'],
+                    $this->squeezeOptions['keepImportantComments'],
+                    $this->squeezeOptions['specialVarRx']
+                );
+                break;
+        }
+
+        return false;
+    }
+
+    /**
+     * Single line option for the JS minimisation.
+     *
+     * @param bool $singleLine
+     *
+     * @return $this
+     */
+    public function singleLine($singleLine)
+    {
+        $this->squeezeOptions['singleLine'] = (bool)$singleLine;
+        return $this;
+    }
+
+    /**
+     * keepImportantComments option for the JS minimisation.
+     *
+     * @param bool $keepImportantComments
+     *
+     * @return $this
+     */
+    public function keepImportantComments($keepImportantComments)
+    {
+        $this->squeezeOptions['keepImportantComments'] = (bool)$keepImportantComments;
+        return $this;
+    }
+
+    /**
+     * specialVarRx option for the JS minimisation.
+     *
+     * @param bool $specialVarRx
+     *
+     * @return $this ;
+     */
+    public function specialVarRx($specialVarRx)
+    {
+        $this->squeezeOptions['specialVarRx'] = (bool)$specialVarRx;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return (string) $this->getMinifiedText();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function run()
+    {
+        if (empty($this->type)) {
+            return Result::error($this, 'Unknown asset type.');
+        }
+
+        if (empty($this->dst)) {
+            return Result::error($this, 'Unknown file destination.');
+        }
+
+        if (file_exists($this->dst) && !is_writable($this->dst)) {
+            return Result::error($this, 'Destination already exists and cannot be overwritten.');
+        }
+
+        $size_before = strlen($this->text);
+        $minified = $this->getMinifiedText();
+
+        if ($minified instanceof Result) {
+            return $minified;
+        } elseif (false === $minified) {
+            return Result::error($this, 'Minification failed.');
+        }
+
+        $size_after = strlen($minified);
+
+        // Minification did not reduce file size, so use original file.
+        if ($size_after > $size_before) {
+            $minified = $this->text;
+            $size_after = $size_before;
+        }
+
+        $dst = $this->dst . '.part';
+        $write_result = file_put_contents($dst, $minified);
+
+        if (false === $write_result) {
+            @unlink($dst);
+            return Result::error($this, 'File write failed.');
+        }
+        // Cannot be cross-volume; should always succeed.
+        @rename($dst, $this->dst);
+        if ($size_before === 0) {
+            $minified_percent = 0;
+        } else {
+            $minified_percent = number_format(100 - ($size_after / $size_before * 100), 1);
+        }
+        $this->printTaskSuccess('Wrote {filepath}', ['filepath' => $this->dst]);
+        $context = [
+            'bytes' => $this->formatBytes($size_after),
+            'reduction' => $this->formatBytes(($size_before - $size_after)),
+            'percentage' => $minified_percent,
+        ];
+        $this->printTaskSuccess('Wrote {bytes} (reduced by {reduction} / {percentage})', $context);
+        return Result::success($this, 'Asset minified.');
+    }
+}