Skip to content

Commit 7c9b72f

Browse files
Merge pull request #1 from php-task-runner/initial-implementation
2 parents 9ac15e4 + 31eb898 commit 7c9b72f

File tree

7 files changed

+303
-5
lines changed

7 files changed

+303
-5
lines changed

.travis.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
language: php
2+
sudo: false
3+
4+
php:
5+
- 7.1
6+
- 7.2
7+
- 7.3
8+
- 7.4
9+
10+
env:
11+
- TEST_SUITE=PHP_CodeSniffer
12+
- TEST_SUITE=PHPUnit
13+
14+
# Only run the coding standards check once.
15+
matrix:
16+
exclude:
17+
- php: 7.1
18+
env: TEST_SUITE=PHP_CodeSniffer
19+
- php: 7.2
20+
env: TEST_SUITE=PHP_CodeSniffer
21+
- php: 7.3
22+
env: TEST_SUITE=PHP_CodeSniffer
23+
24+
before_script:
25+
- composer install
26+
27+
script:
28+
- test ${TEST_SUITE} == "PHP_CodeSniffer" || ./vendor/bin/phpunit tests/
29+
- test ${TEST_SUITE} == "PHPUnit" || ./vendor/bin/phpcs

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[![Build Status](https://travis-ci.com/php-task-runner/scss.svg?branch=master)](https://travis-ci.com/php-task-runner/scss)
2+
3+
This repository provides SCSS commands for OpenEuropa [Task Runner](
4+
https://github.com/openeuropa/task-runner).
5+
6+
## Commands
7+
8+
* `assets:compile-scss`: Compile SCSS to CSS.

composer.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@
44
"keywords": ["task-runner"],
55
"type": "library",
66
"require": {
7-
"php": ">=7.1",
7+
"php": "~7.1",
88
"consolidation/robo": "^1.4.11",
9-
"openeuropa/task-runner": "dev-master",
9+
"openeuropa/task-runner": "^1.0.0-beta6",
1010
"scssphp/scssphp": "~1.1"
1111
},
1212
"require-dev": {
13-
"phpunit/phpunit": "~6 || ~7 || ~8 || ~9",
14-
"squizlabs/php_codesniffer": "^3.0@dev"
13+
"phpunit/phpunit": "~7 || ~8 || ~9",
14+
"slevomat/coding-standard": "~6",
15+
"squizlabs/php_codesniffer": "~3"
1516
},
1617
"license": "EUPL-1.2",
1718
"authors": [
@@ -27,7 +28,7 @@
2728
},
2829
"autoload-dev": {
2930
"psr-4": {
30-
"TaskRunner\\Scss\\Tests\\": "./tests/"
31+
"TaskRunner\\Scss\\Tests\\": "./tests/src/"
3132
}
3233
},
3334
"config": {

phpcs.xml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ruleset name="TaskRunner/Scss">
3+
<description>PHP CodeSniffer configuration for the php-task-runner/scss library.</description>
4+
<config name="installed_paths" value="../../slevomat/coding-standard"/>
5+
<rule ref="PSR12">
6+
<exclude name="Generic.Files.LineLength.TooLong" />
7+
<exclude name="PSR2.Classes.ClassDeclaration.CloseBraceAfterBody" />
8+
</rule>
9+
<rule ref="SlevomatCodingStandard.TypeHints.DeclareStrictTypes">
10+
<properties>
11+
<property name="newlinesCountBetweenOpenTagAndDeclare" value="2" />
12+
<property name="newlinesCountAfterDeclare" value="2" />
13+
<property name="spacesCountAroundEqualsSign" value="0" />
14+
</properties>
15+
</rule>
16+
<rule ref="SlevomatCodingStandard.Arrays.DisallowImplicitArrayCreation" />
17+
<rule ref="SlevomatCodingStandard.ControlStructures.DisallowContinueWithoutIntegerOperandInSwitch" />
18+
<rule ref="SlevomatCodingStandard.ControlStructures.RequireNullCoalesceOperator" />
19+
<rule ref="SlevomatCodingStandard.Operators.DisallowEqualOperators" />
20+
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses" />
21+
<rule ref="SlevomatCodingStandard.Namespaces.UseFromSameNamespace" />
22+
<rule ref="SlevomatCodingStandard.PHP.UselessParentheses" />
23+
<rule ref="SlevomatCodingStandard.Variables.UnusedVariable" />
24+
<rule ref="SlevomatCodingStandard.Arrays.TrailingArrayComma" />
25+
<rule ref="SlevomatCodingStandard.Namespaces.AlphabeticallySortedUses" />
26+
<rule ref="SlevomatCodingStandard.Namespaces.NamespaceDeclaration" />
27+
<rule ref="SlevomatCodingStandard.Namespaces.NamespaceSpacing" />
28+
<rule ref="SlevomatCodingStandard.Classes.ClassConstantVisibility" />
29+
<rule ref="SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing" />
30+
<rule ref="SlevomatCodingStandard.TypeHints.NullableTypeForNullDefaultValue" />
31+
<rule ref="SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash" />
32+
<file>src</file>
33+
<file>tests</file>
34+
<arg name="report" value="full"/>
35+
<arg value="p"/>
36+
</ruleset>
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TaskRunner\Scss\TaskRunner\Commands;
6+
7+
use Consolidation\AnnotatedCommand\CommandData;
8+
use OpenEuropa\TaskRunner\Commands\AbstractCommands;
9+
use Robo\Collection\CollectionBuilder;
10+
use Robo\Task\Assets\loadTasks;
11+
use Symfony\Component\Console\Input\InputOption;
12+
13+
/**
14+
* Command wrapper for the "taskScss" task that is included in Robo.
15+
*
16+
* @see \Robo\Task\Assets\loadTasks
17+
*/
18+
class ScssCommands extends AbstractCommands
19+
{
20+
use loadTasks;
21+
22+
/**
23+
* List of formatters that is offered by the ScssPhp compiler.
24+
*
25+
* @see \ScssPhp\ScssPhp\Formatter
26+
*/
27+
protected const SCSS_FORMATTERS = ['compact', 'compressed', 'crunched', 'expanded', 'nested'];
28+
29+
/**
30+
* Compile SCSS to CSS.
31+
*
32+
* @command assets:compile-scss
33+
*
34+
* @param string $input_file The path to the SCSS file to process
35+
* @param string $output_file The path where to store the compiled CSS file
36+
* @option style Set the output format (compact, compressed, crunched, expanded, or nested)
37+
* @option import-dir Set an import path
38+
*
39+
* @param array $options
40+
*
41+
* @return \Robo\Collection\CollectionBuilder
42+
*/
43+
public function compileScss(string $input_file, string $output_file, array $options = [
44+
'style' => InputOption::VALUE_REQUIRED,
45+
'import-dir' => [],
46+
]): CollectionBuilder
47+
{
48+
$scss = $this->taskScss([$input_file => $output_file]);
49+
50+
if ($options['style']) {
51+
$scss->setFormatter('ScssPhp\\ScssPhp\\Formatter\\' . ucfirst($options['style']));
52+
}
53+
54+
foreach ($options['import-dir'] as $import_dir) {
55+
$scss->addImportPath($import_dir);
56+
}
57+
58+
return $this->collectionBuilder()->addTask($scss);
59+
}
60+
61+
/**
62+
* @hook pre-validate assets:compile-scss
63+
*/
64+
public function preValidateCompileScss(CommandData $commandData): void
65+
{
66+
$input = $commandData->input();
67+
$style = $input->getOption('style');
68+
if ($style) {
69+
// Ensure case insensitive matching for the style option.
70+
$input->setOption('style', strtolower($style));
71+
}
72+
}
73+
74+
/**
75+
* @hook validate assets:compile-scss
76+
*/
77+
public function validateCompileScss(CommandData $commandData): void
78+
{
79+
$input = $commandData->input();
80+
$input_file = $input->getArgument('input_file');
81+
if (!is_file($input_file) || !is_readable($input_file)) {
82+
throw new \Exception(sprintf('Input file "%s" does not exist or is not readable', $input_file));
83+
}
84+
85+
$style = $input->getOption('style');
86+
if ($style && !in_array($style, self::SCSS_FORMATTERS)) {
87+
throw new \Exception(sprintf('Unknown style "%s"', $style));
88+
}
89+
90+
$import_dirs = $input->getOption('import-dir');
91+
foreach ($import_dirs as $import_dir) {
92+
if (!is_dir($import_dir) || !is_readable($import_dir)) {
93+
throw new \Exception(sprintf('Import dir "%s" does not exist or is not readable', $import_dir));
94+
}
95+
}
96+
}
97+
98+
}

tests/fixtures/example.scss

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Example SCSS file to test the `assets:compile-scss` command.
2+
$dark: #111;
3+
nav {
4+
ul {
5+
margin: 0;
6+
li {
7+
color: $dark;
8+
}
9+
}
10+
}

tests/src/ScssCommandsTest.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace TaskRunner\Scss\Tests;
6+
7+
use Composer\Autoload\ClassLoader;
8+
use OpenEuropa\TaskRunner\TaskRunner;
9+
use PHPUnit\Framework\TestCase;
10+
use Symfony\Component\Console\Input\StringInput;
11+
use Symfony\Component\Console\Output\BufferedOutput;
12+
13+
/**
14+
* Tests the command wrappers for Robo "assets" tasks.
15+
*
16+
* @coversDefaultClass \TaskRunner\Scss\TaskRunner\Commands\ScssCommands
17+
* @phpcs:disable SlevomatCodingStandard.Arrays.TrailingArrayComma
18+
*/
19+
final class ScssCommandsTest extends TestCase
20+
{
21+
22+
/**
23+
* @param string $style
24+
* The CSS style to be generated.
25+
* @param string $expected
26+
* The expected compiled CSS.
27+
*
28+
* @covers ::compileScss
29+
* @dataProvider compileScssDataProvider
30+
*/
31+
public function testCompileScss(string $style, string $expected): void
32+
{
33+
$command = sprintf(
34+
'assets:compile-scss --working-dir=%s --style=%s %s %s',
35+
sys_get_temp_dir(),
36+
$style,
37+
__DIR__ . '/../fixtures/example.scss',
38+
'output.css'
39+
);
40+
$input = new StringInput($command);
41+
$output = new BufferedOutput();
42+
$runner = new TaskRunner($input, $output, $this->getClassLoader());
43+
$runner->run();
44+
45+
$actual = file_get_contents(sys_get_temp_dir() . '/output.css');
46+
$this->assertEquals($expected, $actual);
47+
}
48+
49+
/**
50+
* Data provider for ::testCompileScss().
51+
*
52+
* @return array[]
53+
* An array of test cases, each test case an array with two elements:
54+
* - A string containing the CSS style to be generated.
55+
* - A string containing the expected compiled CSS.
56+
*/
57+
public function compileScssDataProvider(): array
58+
{
59+
return [
60+
[
61+
'compact',
62+
<<<CSS
63+
nav ul { margin:0; }
64+
65+
nav ul li { color:#111; }
66+
67+
68+
CSS
69+
],
70+
[
71+
'compressed',
72+
<<<CSS
73+
nav ul{margin:0}nav ul li{color:#111}
74+
CSS
75+
],
76+
[
77+
'crunched',
78+
<<<CSS
79+
nav ul{margin:0}nav ul li{color:#111}
80+
CSS
81+
],
82+
[
83+
'expanded',
84+
<<<CSS
85+
nav ul {
86+
margin: 0;
87+
}
88+
nav ul li {
89+
color: #111;
90+
}
91+
92+
CSS
93+
],
94+
[
95+
'nested',
96+
<<<CSS
97+
nav ul {
98+
margin: 0; }
99+
nav ul li {
100+
color: #111; }
101+
102+
CSS
103+
],
104+
];
105+
}
106+
107+
/**
108+
* Returns the Composer classloader.
109+
*
110+
* @return \Composer\Autoload\ClassLoader
111+
*/
112+
protected function getClassLoader(): ClassLoader
113+
{
114+
return require __DIR__ . '/../../vendor/autoload.php';
115+
}
116+
}

0 commit comments

Comments
 (0)