Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
language: php
sudo: false

php:
- 7.1
- 7.2
- 7.3
- 7.4

env:
- TEST_SUITE=PHP_CodeSniffer
- TEST_SUITE=PHPUnit

# Only run the coding standards check once.
matrix:
exclude:
- php: 7.1
env: TEST_SUITE=PHP_CodeSniffer
- php: 7.2
env: TEST_SUITE=PHP_CodeSniffer
- php: 7.3
env: TEST_SUITE=PHP_CodeSniffer

before_script:
- composer install

script:
- test ${TEST_SUITE} == "PHP_CodeSniffer" || ./vendor/bin/phpunit tests/
- test ${TEST_SUITE} == "PHPUnit" || ./vendor/bin/phpcs
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[![Build Status](https://travis-ci.com/php-task-runner/scss.svg?branch=master)](https://travis-ci.com/php-task-runner/scss)

This repository provides SCSS commands for OpenEuropa [Task Runner](
https://github.com/openeuropa/task-runner).

## Commands

* `assets:compile-scss`: Compile SCSS to CSS.
11 changes: 6 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@
"keywords": ["task-runner"],
"type": "library",
"require": {
"php": ">=7.1",
"php": "~7.1",
"consolidation/robo": "^1.4.11",
"openeuropa/task-runner": "dev-master",
"openeuropa/task-runner": "^1.0.0-beta6",
"scssphp/scssphp": "~1.1"
},
"require-dev": {
"phpunit/phpunit": "~6 || ~7 || ~8 || ~9",
"squizlabs/php_codesniffer": "^3.0@dev"
"phpunit/phpunit": "~7 || ~8 || ~9",
"slevomat/coding-standard": "~6",
"squizlabs/php_codesniffer": "~3"
},
"license": "EUPL-1.2",
"authors": [
Expand All @@ -27,7 +28,7 @@
},
"autoload-dev": {
"psr-4": {
"TaskRunner\\Scss\\Tests\\": "./tests/"
"TaskRunner\\Scss\\Tests\\": "./tests/src/"
}
},
"config": {
Expand Down
36 changes: 36 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<ruleset name="TaskRunner/Scss">
<description>PHP CodeSniffer configuration for the php-task-runner/scss library.</description>
<config name="installed_paths" value="../../slevomat/coding-standard"/>
<rule ref="PSR12">
<exclude name="Generic.Files.LineLength.TooLong" />
<exclude name="PSR2.Classes.ClassDeclaration.CloseBraceAfterBody" />
</rule>
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
<properties>
<property name="newlinesCountBetweenOpenTagAndDeclare" value="2" />
<property name="newlinesCountAfterDeclare" value="2" />
<property name="spacesCountAroundEqualsSign" value="0" />
</properties>
</rule>
<rule ref="SlevomatCodingStandard.Arrays.DisallowImplicitArrayCreation" />
<rule ref="SlevomatCodingStandard.ControlStructures.DisallowContinueWithoutIntegerOperandInSwitch" />
<rule ref="SlevomatCodingStandard.ControlStructures.RequireNullCoalesceOperator" />
<rule ref="SlevomatCodingStandard.Operators.DisallowEqualOperators" />
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses" />
<rule ref="SlevomatCodingStandard.Namespaces.UseFromSameNamespace" />
<rule ref="SlevomatCodingStandard.PHP.UselessParentheses" />
<rule ref="SlevomatCodingStandard.Variables.UnusedVariable" />
<rule ref="SlevomatCodingStandard.Arrays.TrailingArrayComma" />
<rule ref="SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses" />
<rule ref="SlevomatCodingStandard.Namespaces.NamespaceDeclaration" />
<rule ref="SlevomatCodingStandard.Namespaces.NamespaceSpacing" />
<rule ref="SlevomatCodingStandard.Classes.ClassConstantVisibility" />
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing" />
<rule ref="SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue" />
<rule ref="SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash" />
<file>src</file>
<file>tests</file>
<arg name="report" value="full"/>
<arg value="p"/>
</ruleset>
98 changes: 98 additions & 0 deletions src/TaskRunner/Commands/ScssCommands.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

declare(strict_types=1);

namespace TaskRunner\Scss\TaskRunner\Commands;

use Consolidation\AnnotatedCommand\CommandData;
use OpenEuropa\TaskRunner\Commands\AbstractCommands;
use Robo\Collection\CollectionBuilder;
use Robo\Task\Assets\loadTasks;
use Symfony\Component\Console\Input\InputOption;

/**
* Command wrapper for the "taskScss" task that is included in Robo.
*
* @see \Robo\Task\Assets\loadTasks
*/
class ScssCommands extends AbstractCommands
{
use loadTasks;

/**
* List of formatters that is offered by the ScssPhp compiler.
*
* @see \ScssPhp\ScssPhp\Formatter
*/
protected const SCSS_FORMATTERS = ['compact', 'compressed', 'crunched', 'expanded', 'nested'];

/**
* Compile SCSS to CSS.
*
* @command assets:compile-scss
*
* @param string $input_file The path to the SCSS file to process
* @param string $output_file The path where to store the compiled CSS file
* @option style Set the output format (compact, compressed, crunched, expanded, or nested)
* @option import-dir Set an import path
*
* @param array $options
*
* @return \Robo\Collection\CollectionBuilder
*/
public function compileScss(string $input_file, string $output_file, array $options = [
'style' => InputOption::VALUE_REQUIRED,
'import-dir' => [],
]): CollectionBuilder
{
$scss = $this->taskScss([$input_file => $output_file]);

if ($options['style']) {
$scss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\' . ucfirst($options['style']));
}

foreach ($options['import-dir'] as $import_dir) {
$scss->addImportPath($import_dir);
}

return $this->collectionBuilder()->addTask($scss);
}

/**
* @hook pre-validate assets:compile-scss
*/
public function preValidateCompileScss(CommandData $commandData): void
{
$input = $commandData->input();
$style = $input->getOption('style');
if ($style) {
// Ensure case insensitive matching for the style option.
$input->setOption('style', strtolower($style));
}
}

/**
* @hook validate assets:compile-scss
*/
public function validateCompileScss(CommandData $commandData): void
{
$input = $commandData->input();
$input_file = $input->getArgument('input_file');
if (!is_file($input_file) || !is_readable($input_file)) {
throw new \Exception(sprintf('Input file "%s" does not exist or is not readable', $input_file));
}

$style = $input->getOption('style');
if ($style && !in_array($style, self::SCSS_FORMATTERS)) {
throw new \Exception(sprintf('Unknown style "%s"', $style));
}

$import_dirs = $input->getOption('import-dir');
foreach ($import_dirs as $import_dir) {
if (!is_dir($import_dir) || !is_readable($import_dir)) {
throw new \Exception(sprintf('Import dir "%s" does not exist or is not readable', $import_dir));
}
}
}

}
10 changes: 10 additions & 0 deletions tests/fixtures/example.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Example SCSS file to test the `assets:compile-scss` command.
$dark: #111;
nav {
ul {
margin: 0;
li {
color: $dark;
}
}
}
116 changes: 116 additions & 0 deletions tests/src/ScssCommandsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

declare(strict_types=1);

namespace TaskRunner\Scss\Tests;

use Composer\Autoload\ClassLoader;
use OpenEuropa\TaskRunner\TaskRunner;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\StringInput;
use Symfony\Component\Console\Output\BufferedOutput;

/**
* Tests the command wrappers for Robo "assets" tasks.
*
* @coversDefaultClass \TaskRunner\Scss\TaskRunner\Commands\ScssCommands
* @phpcs:disable SlevomatCodingStandard.Arrays.TrailingArrayComma
*/
final class ScssCommandsTest extends TestCase
{

/**
* @param string $style
* The CSS style to be generated.
* @param string $expected
* The expected compiled CSS.
*
* @covers ::compileScss
* @dataProvider compileScssDataProvider
*/
public function testCompileScss(string $style, string $expected): void
{
$command = sprintf(
'assets:compile-scss --working-dir=%s --style=%s %s %s',
sys_get_temp_dir(),
$style,
__DIR__ . '/../fixtures/example.scss',
'output.css'
);
$input = new StringInput($command);
$output = new BufferedOutput();
$runner = new TaskRunner($input, $output, $this->getClassLoader());
$runner->run();

$actual = file_get_contents(sys_get_temp_dir() . '/output.css');
$this->assertEquals($expected, $actual);
}

/**
* Data provider for ::testCompileScss().
*
* @return array[]
* An array of test cases, each test case an array with two elements:
* - A string containing the CSS style to be generated.
* - A string containing the expected compiled CSS.
*/
public function compileScssDataProvider(): array
{
return [
[
'compact',
<<<CSS
nav ul { margin:0; }

nav ul li { color:#111; }


CSS
],
[
'compressed',
<<<CSS
nav ul{margin:0}nav ul li{color:#111}
CSS
],
[
'crunched',
<<<CSS
nav ul{margin:0}nav ul li{color:#111}
CSS
],
[
'expanded',
<<<CSS
nav ul {
margin: 0;
}
nav ul li {
color: #111;
}

CSS
],
[
'nested',
<<<CSS
nav ul {
margin: 0; }
nav ul li {
color: #111; }

CSS
],
];
}

/**
* Returns the Composer classloader.
*
* @return \Composer\Autoload\ClassLoader
*/
protected function getClassLoader(): ClassLoader
{
return require __DIR__ . '/../../vendor/autoload.php';
}
}