├── .gitignore
├── .scrutinizer.yml
├── .travis.yml
├── README.md
├── bin
├── css2scss
└── css2scss.bat
├── composer.json
├── composer.lock
├── composer.phar
├── example.php
├── phpunit.php
├── phpunit.xml
├── src
├── Css2Scss.php
└── tokens
│ ├── ScssRule.php
│ └── ScssRuleList.php
└── tests
└── Css2ScssTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | .idea/
3 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | checks:
2 | php:
3 | code_rating: true
4 | duplication: true
5 | tools:
6 | external_code_coverage: true
7 | php_code_sniffer: true
8 | php_mess_detector: true
9 | php_cs_fixer:
10 | config: { level: psr2 }
11 | filter:
12 | paths: [src/*]
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.4
5 | - 5.5
6 | - 5.6
7 | - 7.0
8 | - hhvm
9 |
10 | before_script:
11 | - composer self-update
12 | - composer install --no-interaction --prefer-source --dev
13 |
14 | script:
15 | - mkdir -p build/logs
16 | - phpunit --coverage-clover build/logs/clover.xml
17 |
18 | after_script:
19 | - wget https://scrutinizer-ci.com/ocular.phar
20 | - php ocular.phar code-coverage:upload --format=php-clover build/logs/clover.xml
21 |
22 | notifications:
23 | email: false
24 |
25 | sudo: false
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/ortic/css2scss)
2 | [](https://scrutinizer-ci.com/g/ortic/css2scss/)
3 | [](https://scrutinizer-ci.com/g/ortic/css2scss/)
4 |
5 | css2less
6 | ========
7 |
8 | this library aims to convert CSS files into SCSS files.
9 |
10 | Currently used by http://www.css2scss.net/
11 |
12 | example
13 | =======
14 |
15 | The code below takes a few CSS instructions and prints them in a more SCSS like form:
16 |
17 | ```php
18 | $cssContent = 'body p { font-family: arial; }';
19 | $css2lessParser = new \Ortic\Css2Scss\Css2Scss($cssContent);
20 | echo $css2lessParser->getScss();
21 | ```
22 |
23 | output:
24 |
25 | ```
26 | body {
27 | p {
28 | font-family: arial;
29 | }
30 | }
31 | ```
--------------------------------------------------------------------------------
/bin/css2scss:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | argv = $argv;
32 |
33 | // remove first item from array, it only contains a path to the script
34 | array_shift($this->argv);
35 |
36 | $this->parseArguments();
37 | $this->checkMandatoryArguments();
38 | $this->run();
39 | }
40 |
41 | /**
42 | * Loops through the options specified in the getOptions methods and assigns them to the proper class properties
43 | */
44 | protected function parseArguments()
45 | {
46 | $options = $this->getOptions();
47 | $currentVariable = null;
48 |
49 | foreach ($this->argv as $argument) {
50 | if (array_key_exists($argument, $options)) {
51 | $currentVariable = $options[$argument]['assignmentTarget'];
52 | } else {
53 | if (is_null($currentVariable)) {
54 | echo "Invalid command line arguments specified!\n\n";
55 | $this->showHelp();
56 | die();
57 | }
58 | $this->$currentVariable = $argument;
59 | $currentVariable = null;
60 | }
61 | }
62 | }
63 |
64 | /**
65 | * Checks if all mandatory arguments are specified
66 | */
67 | protected function checkMandatoryArguments()
68 | {
69 | $options = $this->getOptions();
70 | foreach ($options as $optionKey => $option) {
71 | if ($option['mandatory']) {
72 | $assignmentTarget = $option['assignmentTarget'];
73 | if (empty($this->$assignmentTarget)) {
74 | echo sprintf("Please specify mandatory argument: %s\n\n", $optionKey);
75 | $this->showHelp();
76 | die();
77 | }
78 | }
79 | }
80 | }
81 |
82 | /**
83 | * Show a usage example and all available options
84 | */
85 | protected function showHelp()
86 | {
87 | echo "Usage:\t\n css2scss --css input.css --scss output.scss\n\n";
88 | echo "Arguments:\n";
89 | $options = $this->getOptions();
90 | foreach ($options as $optionKey => $option) {
91 | echo " " . str_pad($optionKey, 10) . $option['explanation'] . "\n";
92 | }
93 | }
94 |
95 | /**
96 | * Returns an array of an array having three properties:
97 | * - explanation: An explanation for the user about the argument
98 | * - mandatory: true if mandatory
99 | * - assignmentTarget: The name of the class property where to keep the argument value
100 | *
101 | * @return array options
102 | */
103 | protected function getOptions()
104 | {
105 | return array(
106 | '--css' => array(
107 | 'explanation' => 'The css file you want to convert to a scss file',
108 | 'mandatory' => true,
109 | 'assignmentTarget' => 'cssFileName',
110 | ),
111 | '--scss' => array(
112 | 'explanation' => '(optional) Path where you want to save the converted file',
113 | 'mandatory' => false,
114 | 'assignmentTarget' => 'scssFileName',
115 | ),
116 | );
117 | }
118 |
119 | /**
120 | * Starts the conversion
121 | */
122 | public function run()
123 | {
124 | if (!file_exists($this->cssFileName)) {
125 | echo sprintf("CSS File \"%s\" not found!\n", $this->cssFileName);
126 | die();
127 | }
128 |
129 | $cssFileContent = file_get_contents($this->cssFileName);
130 | $css2scssParser = new \Ortic\Css2Scss\Css2Scss($cssFileContent);
131 | $scssOutput = $css2scssParser->getScss();
132 |
133 | if ($this->scssFileName == '') {
134 | echo $scssOutput;
135 | } else {
136 | file_put_contents($this->scssFileName, $scssOutput);
137 | echo sprintf("LESS output saved in \"%s\"\n", $this->scssFileName);
138 | }
139 | }
140 | }
141 |
142 | (new Css2Scss($argv))->run();
143 |
144 |
--------------------------------------------------------------------------------
/bin/css2scss.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | php %~dp0\css2scss %*
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ortic/css2scss",
3 | "description": "css to scss converter",
4 | "minimum-stability": "stable",
5 | "license": "proprietary",
6 | "authors": [
7 | {
8 | "name": "Remo Laubacher",
9 | "email": "remo.laubacher@ortic.com"
10 | }
11 | ],
12 | "require": {
13 | "php": ">=5.4.4",
14 | "natxet/cssmin": "~3.0"
15 | },
16 | "require-dev": {
17 | "phpunit/phpunit": "~4.0",
18 | "satooshi/php-coveralls": "dev-master",
19 | "nette/nette": "~2.1.3",
20 | "apigen/apigen": "2.8.0"
21 | },
22 | "autoload": {
23 | "psr-4": {
24 | "Ortic\\Css2Scss\\": "src/"
25 | }
26 | },
27 | "bin": [
28 | "bin/css2scss.bat",
29 | "bin/css2scss"
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 | "This file is @generated automatically"
6 | ],
7 | "hash": "d6644c72e87ed5283508c34625e8225d",
8 | "packages": [
9 | {
10 | "name": "natxet/CssMin",
11 | "version": "v3.0.4",
12 | "source": {
13 | "type": "git",
14 | "url": "https://github.com/natxet/CssMin.git",
15 | "reference": "92de3fe3ccb4f8298d31952490ef7d5395855c39"
16 | },
17 | "dist": {
18 | "type": "zip",
19 | "url": "https://api.github.com/repos/natxet/CssMin/zipball/92de3fe3ccb4f8298d31952490ef7d5395855c39",
20 | "reference": "92de3fe3ccb4f8298d31952490ef7d5395855c39",
21 | "shasum": ""
22 | },
23 | "require": {
24 | "php": ">=5.0"
25 | },
26 | "type": "library",
27 | "extra": {
28 | "branch-alias": {
29 | "dev-master": "3.0-dev"
30 | }
31 | },
32 | "autoload": {
33 | "classmap": [
34 | "src/"
35 | ]
36 | },
37 | "notification-url": "https://packagist.org/downloads/",
38 | "license": [
39 | "MIT"
40 | ],
41 | "authors": [
42 | {
43 | "name": "Joe Scylla",
44 | "email": "joe.scylla@gmail.com",
45 | "homepage": "https://profiles.google.com/joe.scylla"
46 | }
47 | ],
48 | "description": "Minifying CSS",
49 | "homepage": "http://code.google.com/p/cssmin/",
50 | "keywords": [
51 | "css",
52 | "minify"
53 | ],
54 | "time": "2015-09-25 11:13:11"
55 | }
56 | ],
57 | "packages-dev": [
58 | {
59 | "name": "andrewsville/php-token-reflection",
60 | "version": "1.4.0",
61 | "source": {
62 | "type": "git",
63 | "url": "https://github.com/Andrewsville/PHP-Token-Reflection.git",
64 | "reference": "e6d0ac2baf66cdf154be34c3d2a2aa1bd4b426ee"
65 | },
66 | "dist": {
67 | "type": "zip",
68 | "url": "https://api.github.com/repos/Andrewsville/PHP-Token-Reflection/zipball/e6d0ac2baf66cdf154be34c3d2a2aa1bd4b426ee",
69 | "reference": "e6d0ac2baf66cdf154be34c3d2a2aa1bd4b426ee",
70 | "shasum": ""
71 | },
72 | "require": {
73 | "ext-tokenizer": "*",
74 | "php": ">=5.3.0"
75 | },
76 | "type": "library",
77 | "autoload": {
78 | "psr-0": {
79 | "TokenReflection": "./"
80 | }
81 | },
82 | "notification-url": "https://packagist.org/downloads/",
83 | "license": [
84 | "BSD-3"
85 | ],
86 | "authors": [
87 | {
88 | "name": "Ondřej Nešpor",
89 | "homepage": "https://github.com/andrewsville"
90 | },
91 | {
92 | "name": "Jaroslav Hanslík",
93 | "homepage": "https://github.com/kukulich"
94 | }
95 | ],
96 | "description": "Library emulating the PHP internal reflection using just the tokenized source code.",
97 | "homepage": "http://andrewsville.github.com/PHP-Token-Reflection/",
98 | "keywords": [
99 | "library",
100 | "reflection",
101 | "tokenizer"
102 | ],
103 | "time": "2014-08-06 16:37:08"
104 | },
105 | {
106 | "name": "apigen/apigen",
107 | "version": "2.8.0",
108 | "source": {
109 | "type": "git",
110 | "url": "https://github.com/apigen/ApiGen.git",
111 | "reference": "4987551632c3ad3fb7e89cf6dc3fe601e45578c3"
112 | },
113 | "dist": {
114 | "type": "zip",
115 | "url": "https://api.github.com/repos/apigen/ApiGen/zipball/4987551632c3ad3fb7e89cf6dc3fe601e45578c3",
116 | "reference": "4987551632c3ad3fb7e89cf6dc3fe601e45578c3",
117 | "shasum": ""
118 | },
119 | "require": {
120 | "andrewsville/php-token-reflection": ">=1.3.1",
121 | "dg/texy": ">=2.1.0",
122 | "kukulich/fshl": ">=2.1.0",
123 | "nette/nette": ">=2.0.5",
124 | "php": ">=5.3.0"
125 | },
126 | "suggest": {
127 | "ext-bz2": "*",
128 | "ext-phar": "*",
129 | "ext-zip": "*",
130 | "ext-zlib": "*"
131 | },
132 | "bin": [
133 | "apigen.php"
134 | ],
135 | "type": "library",
136 | "extra": {
137 | "branch-alias": {
138 | "dev-develop": "3.0.0-dev"
139 | }
140 | },
141 | "autoload": {
142 | "psr-0": {
143 | "ApiGen": "./"
144 | }
145 | },
146 | "notification-url": "https://packagist.org/downloads/",
147 | "license": [
148 | "BSD-3-Clause"
149 | ],
150 | "authors": [
151 | {
152 | "name": "David Grudl",
153 | "homepage": "http://davidgrudl.com"
154 | },
155 | {
156 | "name": "Ondřej Nešpor",
157 | "homepage": "https://github.com/andrewsville"
158 | },
159 | {
160 | "name": "Jaroslav Hanslík",
161 | "homepage": "https://github.com/kukulich"
162 | }
163 | ],
164 | "description": "API documentation generator for PHP 5.3+",
165 | "homepage": "http://apigen.org/",
166 | "keywords": [
167 | "api",
168 | "docblock",
169 | "documentation",
170 | "generator",
171 | "phpDocumentor",
172 | "phpdoc"
173 | ],
174 | "time": "2012-09-29 17:34:02"
175 | },
176 | {
177 | "name": "dg/texy",
178 | "version": "v2.8.2",
179 | "source": {
180 | "type": "git",
181 | "url": "https://github.com/dg/texy.git",
182 | "reference": "e21cbfcff0a542cf691082df7427911495524ded"
183 | },
184 | "dist": {
185 | "type": "zip",
186 | "url": "https://api.github.com/repos/dg/texy/zipball/e21cbfcff0a542cf691082df7427911495524ded",
187 | "reference": "e21cbfcff0a542cf691082df7427911495524ded",
188 | "shasum": ""
189 | },
190 | "require": {
191 | "php": ">=5.4.4"
192 | },
193 | "replace": {
194 | "dg/texy": "self.version"
195 | },
196 | "require-dev": {
197 | "nette/tester": "~1.5"
198 | },
199 | "type": "library",
200 | "autoload": {
201 | "classmap": [
202 | "src/"
203 | ],
204 | "files": [
205 | "src/texy.php"
206 | ]
207 | },
208 | "notification-url": "https://packagist.org/downloads/",
209 | "license": [
210 | "BSD-3-Clause",
211 | "GPL-2.0",
212 | "GPL-3.0"
213 | ],
214 | "authors": [
215 | {
216 | "name": "David Grudl",
217 | "homepage": "https://davidgrudl.com"
218 | }
219 | ],
220 | "description": "Texy converts plain text in easy to read Texy syntax into structurally valid (X)HTML. It supports adding of images, links, nested lists, tables and has full support for CSS. Texy supports hyphenation of long words (which reflects language rules), clickable emails and URL (emails are obfuscated against spambots), national typographic single and double quotation marks, ellipses, em dashes, dimension sign, nonbreakable spaces (e.g. in phone numbers), acronyms, arrows and many others. Texy code can optionally contain HTML tags.",
221 | "homepage": "http://texy.info",
222 | "keywords": [
223 | "html",
224 | "markdown",
225 | "markup language",
226 | "plain text",
227 | "text",
228 | "textile",
229 | "texy",
230 | "wiki",
231 | "xhtml"
232 | ],
233 | "time": "2015-11-07 22:17:49"
234 | },
235 | {
236 | "name": "doctrine/instantiator",
237 | "version": "1.0.5",
238 | "source": {
239 | "type": "git",
240 | "url": "https://github.com/doctrine/instantiator.git",
241 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
242 | },
243 | "dist": {
244 | "type": "zip",
245 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
246 | "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
247 | "shasum": ""
248 | },
249 | "require": {
250 | "php": ">=5.3,<8.0-DEV"
251 | },
252 | "require-dev": {
253 | "athletic/athletic": "~0.1.8",
254 | "ext-pdo": "*",
255 | "ext-phar": "*",
256 | "phpunit/phpunit": "~4.0",
257 | "squizlabs/php_codesniffer": "~2.0"
258 | },
259 | "type": "library",
260 | "extra": {
261 | "branch-alias": {
262 | "dev-master": "1.0.x-dev"
263 | }
264 | },
265 | "autoload": {
266 | "psr-4": {
267 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
268 | }
269 | },
270 | "notification-url": "https://packagist.org/downloads/",
271 | "license": [
272 | "MIT"
273 | ],
274 | "authors": [
275 | {
276 | "name": "Marco Pivetta",
277 | "email": "ocramius@gmail.com",
278 | "homepage": "http://ocramius.github.com/"
279 | }
280 | ],
281 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
282 | "homepage": "https://github.com/doctrine/instantiator",
283 | "keywords": [
284 | "constructor",
285 | "instantiate"
286 | ],
287 | "time": "2015-06-14 21:17:01"
288 | },
289 | {
290 | "name": "guzzle/guzzle",
291 | "version": "v3.9.3",
292 | "source": {
293 | "type": "git",
294 | "url": "https://github.com/guzzle/guzzle3.git",
295 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9"
296 | },
297 | "dist": {
298 | "type": "zip",
299 | "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9",
300 | "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9",
301 | "shasum": ""
302 | },
303 | "require": {
304 | "ext-curl": "*",
305 | "php": ">=5.3.3",
306 | "symfony/event-dispatcher": "~2.1"
307 | },
308 | "replace": {
309 | "guzzle/batch": "self.version",
310 | "guzzle/cache": "self.version",
311 | "guzzle/common": "self.version",
312 | "guzzle/http": "self.version",
313 | "guzzle/inflection": "self.version",
314 | "guzzle/iterator": "self.version",
315 | "guzzle/log": "self.version",
316 | "guzzle/parser": "self.version",
317 | "guzzle/plugin": "self.version",
318 | "guzzle/plugin-async": "self.version",
319 | "guzzle/plugin-backoff": "self.version",
320 | "guzzle/plugin-cache": "self.version",
321 | "guzzle/plugin-cookie": "self.version",
322 | "guzzle/plugin-curlauth": "self.version",
323 | "guzzle/plugin-error-response": "self.version",
324 | "guzzle/plugin-history": "self.version",
325 | "guzzle/plugin-log": "self.version",
326 | "guzzle/plugin-md5": "self.version",
327 | "guzzle/plugin-mock": "self.version",
328 | "guzzle/plugin-oauth": "self.version",
329 | "guzzle/service": "self.version",
330 | "guzzle/stream": "self.version"
331 | },
332 | "require-dev": {
333 | "doctrine/cache": "~1.3",
334 | "monolog/monolog": "~1.0",
335 | "phpunit/phpunit": "3.7.*",
336 | "psr/log": "~1.0",
337 | "symfony/class-loader": "~2.1",
338 | "zendframework/zend-cache": "2.*,<2.3",
339 | "zendframework/zend-log": "2.*,<2.3"
340 | },
341 | "suggest": {
342 | "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated."
343 | },
344 | "type": "library",
345 | "extra": {
346 | "branch-alias": {
347 | "dev-master": "3.9-dev"
348 | }
349 | },
350 | "autoload": {
351 | "psr-0": {
352 | "Guzzle": "src/",
353 | "Guzzle\\Tests": "tests/"
354 | }
355 | },
356 | "notification-url": "https://packagist.org/downloads/",
357 | "license": [
358 | "MIT"
359 | ],
360 | "authors": [
361 | {
362 | "name": "Michael Dowling",
363 | "email": "mtdowling@gmail.com",
364 | "homepage": "https://github.com/mtdowling"
365 | },
366 | {
367 | "name": "Guzzle Community",
368 | "homepage": "https://github.com/guzzle/guzzle/contributors"
369 | }
370 | ],
371 | "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle",
372 | "homepage": "http://guzzlephp.org/",
373 | "keywords": [
374 | "client",
375 | "curl",
376 | "framework",
377 | "http",
378 | "http client",
379 | "rest",
380 | "web service"
381 | ],
382 | "time": "2015-03-18 18:23:50"
383 | },
384 | {
385 | "name": "kukulich/fshl",
386 | "version": "2.1.0",
387 | "source": {
388 | "type": "git",
389 | "url": "https://github.com/kukulich/fshl.git",
390 | "reference": "974c294ade5d76c0c16b6fe3fd3a584ba999b24f"
391 | },
392 | "dist": {
393 | "type": "zip",
394 | "url": "https://api.github.com/repos/kukulich/fshl/zipball/974c294ade5d76c0c16b6fe3fd3a584ba999b24f",
395 | "reference": "974c294ade5d76c0c16b6fe3fd3a584ba999b24f",
396 | "shasum": ""
397 | },
398 | "require": {
399 | "php": ">=5.3"
400 | },
401 | "type": "library",
402 | "autoload": {
403 | "psr-0": {
404 | "FSHL": "./"
405 | }
406 | },
407 | "notification-url": "https://packagist.org/downloads/",
408 | "license": [
409 | "GPL-2.0+"
410 | ],
411 | "authors": [
412 | {
413 | "name": "Jaroslav Hanslík",
414 | "homepage": "https://github.com/kukulich"
415 | }
416 | ],
417 | "description": "FSHL is a free, open source, universal, fast syntax highlighter written in PHP.",
418 | "homepage": "http://fshl.kukulich.cz/",
419 | "keywords": [
420 | "highlight",
421 | "library",
422 | "syntax"
423 | ],
424 | "time": "2012-09-08 19:00:07"
425 | },
426 | {
427 | "name": "nette/nette",
428 | "version": "v2.1.11",
429 | "source": {
430 | "type": "git",
431 | "url": "https://github.com/nette/nette.git",
432 | "reference": "d9bba819f1ac09a4bc5bc330eb83c17bf2926b9a"
433 | },
434 | "dist": {
435 | "type": "zip",
436 | "url": "https://api.github.com/repos/nette/nette/zipball/d9bba819f1ac09a4bc5bc330eb83c17bf2926b9a",
437 | "reference": "d9bba819f1ac09a4bc5bc330eb83c17bf2926b9a",
438 | "shasum": ""
439 | },
440 | "require": {
441 | "ext-iconv": "*",
442 | "ext-tokenizer": "*",
443 | "php": ">=5.3.1"
444 | },
445 | "replace": {
446 | "latte/latte": "self.version",
447 | "nette/application": "self.version",
448 | "nette/bootstrap": "self.version",
449 | "nette/caching": "self.version",
450 | "nette/component-model": "self.version",
451 | "nette/database": "self.version",
452 | "nette/di": "self.version",
453 | "nette/finder": "self.version",
454 | "nette/forms": "self.version",
455 | "nette/http": "self.version",
456 | "nette/mail": "self.version",
457 | "nette/neon": "self.version",
458 | "nette/php-generator": "self.version",
459 | "nette/reflection": "self.version",
460 | "nette/robot-loader": "self.version",
461 | "nette/safe-stream": "self.version",
462 | "nette/security": "self.version",
463 | "nette/tokenizer": "self.version",
464 | "nette/utils": "self.version",
465 | "tracy/tracy": "self.version"
466 | },
467 | "require-dev": {
468 | "nette/tester": "~1.3"
469 | },
470 | "suggest": {
471 | "ext-fileinfo": "",
472 | "ext-gd": "",
473 | "ext-mbstring": "",
474 | "ext-pdo": ""
475 | },
476 | "type": "library",
477 | "autoload": {
478 | "classmap": [
479 | "Nette/"
480 | ],
481 | "files": [
482 | "Nette/common/shortcuts.php"
483 | ]
484 | },
485 | "notification-url": "https://packagist.org/downloads/",
486 | "license": [
487 | "BSD-3-Clause",
488 | "GPL-2.0",
489 | "GPL-3.0"
490 | ],
491 | "authors": [
492 | {
493 | "name": "David Grudl",
494 | "homepage": "http://davidgrudl.com"
495 | },
496 | {
497 | "name": "Nette Community",
498 | "homepage": "http://nette.org/contributors"
499 | }
500 | ],
501 | "description": "Nette Framework - innovative framework for fast and easy development of secured web applications in PHP. Write less, have cleaner code and your work will bring you joy.",
502 | "homepage": "http://nette.org",
503 | "keywords": [
504 | "Forms",
505 | "database",
506 | "debugging",
507 | "framework",
508 | "mailing",
509 | "mvc",
510 | "templating"
511 | ],
512 | "time": "2015-08-15 09:59:47"
513 | },
514 | {
515 | "name": "phpdocumentor/reflection-docblock",
516 | "version": "2.0.4",
517 | "source": {
518 | "type": "git",
519 | "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
520 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8"
521 | },
522 | "dist": {
523 | "type": "zip",
524 | "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8",
525 | "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8",
526 | "shasum": ""
527 | },
528 | "require": {
529 | "php": ">=5.3.3"
530 | },
531 | "require-dev": {
532 | "phpunit/phpunit": "~4.0"
533 | },
534 | "suggest": {
535 | "dflydev/markdown": "~1.0",
536 | "erusev/parsedown": "~1.0"
537 | },
538 | "type": "library",
539 | "extra": {
540 | "branch-alias": {
541 | "dev-master": "2.0.x-dev"
542 | }
543 | },
544 | "autoload": {
545 | "psr-0": {
546 | "phpDocumentor": [
547 | "src/"
548 | ]
549 | }
550 | },
551 | "notification-url": "https://packagist.org/downloads/",
552 | "license": [
553 | "MIT"
554 | ],
555 | "authors": [
556 | {
557 | "name": "Mike van Riel",
558 | "email": "mike.vanriel@naenius.com"
559 | }
560 | ],
561 | "time": "2015-02-03 12:10:50"
562 | },
563 | {
564 | "name": "phpspec/prophecy",
565 | "version": "v1.5.0",
566 | "source": {
567 | "type": "git",
568 | "url": "https://github.com/phpspec/prophecy.git",
569 | "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7"
570 | },
571 | "dist": {
572 | "type": "zip",
573 | "url": "https://api.github.com/repos/phpspec/prophecy/zipball/4745ded9307786b730d7a60df5cb5a6c43cf95f7",
574 | "reference": "4745ded9307786b730d7a60df5cb5a6c43cf95f7",
575 | "shasum": ""
576 | },
577 | "require": {
578 | "doctrine/instantiator": "^1.0.2",
579 | "phpdocumentor/reflection-docblock": "~2.0",
580 | "sebastian/comparator": "~1.1"
581 | },
582 | "require-dev": {
583 | "phpspec/phpspec": "~2.0"
584 | },
585 | "type": "library",
586 | "extra": {
587 | "branch-alias": {
588 | "dev-master": "1.4.x-dev"
589 | }
590 | },
591 | "autoload": {
592 | "psr-0": {
593 | "Prophecy\\": "src/"
594 | }
595 | },
596 | "notification-url": "https://packagist.org/downloads/",
597 | "license": [
598 | "MIT"
599 | ],
600 | "authors": [
601 | {
602 | "name": "Konstantin Kudryashov",
603 | "email": "ever.zet@gmail.com",
604 | "homepage": "http://everzet.com"
605 | },
606 | {
607 | "name": "Marcello Duarte",
608 | "email": "marcello.duarte@gmail.com"
609 | }
610 | ],
611 | "description": "Highly opinionated mocking framework for PHP 5.3+",
612 | "homepage": "https://github.com/phpspec/prophecy",
613 | "keywords": [
614 | "Double",
615 | "Dummy",
616 | "fake",
617 | "mock",
618 | "spy",
619 | "stub"
620 | ],
621 | "time": "2015-08-13 10:07:40"
622 | },
623 | {
624 | "name": "phpunit/php-code-coverage",
625 | "version": "2.2.4",
626 | "source": {
627 | "type": "git",
628 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
629 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
630 | },
631 | "dist": {
632 | "type": "zip",
633 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
634 | "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
635 | "shasum": ""
636 | },
637 | "require": {
638 | "php": ">=5.3.3",
639 | "phpunit/php-file-iterator": "~1.3",
640 | "phpunit/php-text-template": "~1.2",
641 | "phpunit/php-token-stream": "~1.3",
642 | "sebastian/environment": "^1.3.2",
643 | "sebastian/version": "~1.0"
644 | },
645 | "require-dev": {
646 | "ext-xdebug": ">=2.1.4",
647 | "phpunit/phpunit": "~4"
648 | },
649 | "suggest": {
650 | "ext-dom": "*",
651 | "ext-xdebug": ">=2.2.1",
652 | "ext-xmlwriter": "*"
653 | },
654 | "type": "library",
655 | "extra": {
656 | "branch-alias": {
657 | "dev-master": "2.2.x-dev"
658 | }
659 | },
660 | "autoload": {
661 | "classmap": [
662 | "src/"
663 | ]
664 | },
665 | "notification-url": "https://packagist.org/downloads/",
666 | "license": [
667 | "BSD-3-Clause"
668 | ],
669 | "authors": [
670 | {
671 | "name": "Sebastian Bergmann",
672 | "email": "sb@sebastian-bergmann.de",
673 | "role": "lead"
674 | }
675 | ],
676 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
677 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
678 | "keywords": [
679 | "coverage",
680 | "testing",
681 | "xunit"
682 | ],
683 | "time": "2015-10-06 15:47:00"
684 | },
685 | {
686 | "name": "phpunit/php-file-iterator",
687 | "version": "1.4.1",
688 | "source": {
689 | "type": "git",
690 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
691 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0"
692 | },
693 | "dist": {
694 | "type": "zip",
695 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
696 | "reference": "6150bf2c35d3fc379e50c7602b75caceaa39dbf0",
697 | "shasum": ""
698 | },
699 | "require": {
700 | "php": ">=5.3.3"
701 | },
702 | "type": "library",
703 | "extra": {
704 | "branch-alias": {
705 | "dev-master": "1.4.x-dev"
706 | }
707 | },
708 | "autoload": {
709 | "classmap": [
710 | "src/"
711 | ]
712 | },
713 | "notification-url": "https://packagist.org/downloads/",
714 | "license": [
715 | "BSD-3-Clause"
716 | ],
717 | "authors": [
718 | {
719 | "name": "Sebastian Bergmann",
720 | "email": "sb@sebastian-bergmann.de",
721 | "role": "lead"
722 | }
723 | ],
724 | "description": "FilterIterator implementation that filters files based on a list of suffixes.",
725 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
726 | "keywords": [
727 | "filesystem",
728 | "iterator"
729 | ],
730 | "time": "2015-06-21 13:08:43"
731 | },
732 | {
733 | "name": "phpunit/php-text-template",
734 | "version": "1.2.1",
735 | "source": {
736 | "type": "git",
737 | "url": "https://github.com/sebastianbergmann/php-text-template.git",
738 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
739 | },
740 | "dist": {
741 | "type": "zip",
742 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
743 | "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
744 | "shasum": ""
745 | },
746 | "require": {
747 | "php": ">=5.3.3"
748 | },
749 | "type": "library",
750 | "autoload": {
751 | "classmap": [
752 | "src/"
753 | ]
754 | },
755 | "notification-url": "https://packagist.org/downloads/",
756 | "license": [
757 | "BSD-3-Clause"
758 | ],
759 | "authors": [
760 | {
761 | "name": "Sebastian Bergmann",
762 | "email": "sebastian@phpunit.de",
763 | "role": "lead"
764 | }
765 | ],
766 | "description": "Simple template engine.",
767 | "homepage": "https://github.com/sebastianbergmann/php-text-template/",
768 | "keywords": [
769 | "template"
770 | ],
771 | "time": "2015-06-21 13:50:34"
772 | },
773 | {
774 | "name": "phpunit/php-timer",
775 | "version": "1.0.7",
776 | "source": {
777 | "type": "git",
778 | "url": "https://github.com/sebastianbergmann/php-timer.git",
779 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b"
780 | },
781 | "dist": {
782 | "type": "zip",
783 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
784 | "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b",
785 | "shasum": ""
786 | },
787 | "require": {
788 | "php": ">=5.3.3"
789 | },
790 | "type": "library",
791 | "autoload": {
792 | "classmap": [
793 | "src/"
794 | ]
795 | },
796 | "notification-url": "https://packagist.org/downloads/",
797 | "license": [
798 | "BSD-3-Clause"
799 | ],
800 | "authors": [
801 | {
802 | "name": "Sebastian Bergmann",
803 | "email": "sb@sebastian-bergmann.de",
804 | "role": "lead"
805 | }
806 | ],
807 | "description": "Utility class for timing",
808 | "homepage": "https://github.com/sebastianbergmann/php-timer/",
809 | "keywords": [
810 | "timer"
811 | ],
812 | "time": "2015-06-21 08:01:12"
813 | },
814 | {
815 | "name": "phpunit/php-token-stream",
816 | "version": "1.4.8",
817 | "source": {
818 | "type": "git",
819 | "url": "https://github.com/sebastianbergmann/php-token-stream.git",
820 | "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da"
821 | },
822 | "dist": {
823 | "type": "zip",
824 | "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
825 | "reference": "3144ae21711fb6cac0b1ab4cbe63b75ce3d4e8da",
826 | "shasum": ""
827 | },
828 | "require": {
829 | "ext-tokenizer": "*",
830 | "php": ">=5.3.3"
831 | },
832 | "require-dev": {
833 | "phpunit/phpunit": "~4.2"
834 | },
835 | "type": "library",
836 | "extra": {
837 | "branch-alias": {
838 | "dev-master": "1.4-dev"
839 | }
840 | },
841 | "autoload": {
842 | "classmap": [
843 | "src/"
844 | ]
845 | },
846 | "notification-url": "https://packagist.org/downloads/",
847 | "license": [
848 | "BSD-3-Clause"
849 | ],
850 | "authors": [
851 | {
852 | "name": "Sebastian Bergmann",
853 | "email": "sebastian@phpunit.de"
854 | }
855 | ],
856 | "description": "Wrapper around PHP's tokenizer extension.",
857 | "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
858 | "keywords": [
859 | "tokenizer"
860 | ],
861 | "time": "2015-09-15 10:49:45"
862 | },
863 | {
864 | "name": "phpunit/phpunit",
865 | "version": "4.8.18",
866 | "source": {
867 | "type": "git",
868 | "url": "https://github.com/sebastianbergmann/phpunit.git",
869 | "reference": "fa33d4ad96481b91df343d83e8c8aabed6b1dfd3"
870 | },
871 | "dist": {
872 | "type": "zip",
873 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fa33d4ad96481b91df343d83e8c8aabed6b1dfd3",
874 | "reference": "fa33d4ad96481b91df343d83e8c8aabed6b1dfd3",
875 | "shasum": ""
876 | },
877 | "require": {
878 | "ext-dom": "*",
879 | "ext-json": "*",
880 | "ext-pcre": "*",
881 | "ext-reflection": "*",
882 | "ext-spl": "*",
883 | "php": ">=5.3.3",
884 | "phpspec/prophecy": "^1.3.1",
885 | "phpunit/php-code-coverage": "~2.1",
886 | "phpunit/php-file-iterator": "~1.4",
887 | "phpunit/php-text-template": "~1.2",
888 | "phpunit/php-timer": ">=1.0.6",
889 | "phpunit/phpunit-mock-objects": "~2.3",
890 | "sebastian/comparator": "~1.1",
891 | "sebastian/diff": "~1.2",
892 | "sebastian/environment": "~1.3",
893 | "sebastian/exporter": "~1.2",
894 | "sebastian/global-state": "~1.0",
895 | "sebastian/version": "~1.0",
896 | "symfony/yaml": "~2.1|~3.0"
897 | },
898 | "suggest": {
899 | "phpunit/php-invoker": "~1.1"
900 | },
901 | "bin": [
902 | "phpunit"
903 | ],
904 | "type": "library",
905 | "extra": {
906 | "branch-alias": {
907 | "dev-master": "4.8.x-dev"
908 | }
909 | },
910 | "autoload": {
911 | "classmap": [
912 | "src/"
913 | ]
914 | },
915 | "notification-url": "https://packagist.org/downloads/",
916 | "license": [
917 | "BSD-3-Clause"
918 | ],
919 | "authors": [
920 | {
921 | "name": "Sebastian Bergmann",
922 | "email": "sebastian@phpunit.de",
923 | "role": "lead"
924 | }
925 | ],
926 | "description": "The PHP Unit Testing framework.",
927 | "homepage": "https://phpunit.de/",
928 | "keywords": [
929 | "phpunit",
930 | "testing",
931 | "xunit"
932 | ],
933 | "time": "2015-11-11 11:32:49"
934 | },
935 | {
936 | "name": "phpunit/phpunit-mock-objects",
937 | "version": "2.3.8",
938 | "source": {
939 | "type": "git",
940 | "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
941 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
942 | },
943 | "dist": {
944 | "type": "zip",
945 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
946 | "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
947 | "shasum": ""
948 | },
949 | "require": {
950 | "doctrine/instantiator": "^1.0.2",
951 | "php": ">=5.3.3",
952 | "phpunit/php-text-template": "~1.2",
953 | "sebastian/exporter": "~1.2"
954 | },
955 | "require-dev": {
956 | "phpunit/phpunit": "~4.4"
957 | },
958 | "suggest": {
959 | "ext-soap": "*"
960 | },
961 | "type": "library",
962 | "extra": {
963 | "branch-alias": {
964 | "dev-master": "2.3.x-dev"
965 | }
966 | },
967 | "autoload": {
968 | "classmap": [
969 | "src/"
970 | ]
971 | },
972 | "notification-url": "https://packagist.org/downloads/",
973 | "license": [
974 | "BSD-3-Clause"
975 | ],
976 | "authors": [
977 | {
978 | "name": "Sebastian Bergmann",
979 | "email": "sb@sebastian-bergmann.de",
980 | "role": "lead"
981 | }
982 | ],
983 | "description": "Mock Object library for PHPUnit",
984 | "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
985 | "keywords": [
986 | "mock",
987 | "xunit"
988 | ],
989 | "time": "2015-10-02 06:51:40"
990 | },
991 | {
992 | "name": "psr/log",
993 | "version": "1.0.0",
994 | "source": {
995 | "type": "git",
996 | "url": "https://github.com/php-fig/log.git",
997 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
998 | },
999 | "dist": {
1000 | "type": "zip",
1001 | "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
1002 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
1003 | "shasum": ""
1004 | },
1005 | "type": "library",
1006 | "autoload": {
1007 | "psr-0": {
1008 | "Psr\\Log\\": ""
1009 | }
1010 | },
1011 | "notification-url": "https://packagist.org/downloads/",
1012 | "license": [
1013 | "MIT"
1014 | ],
1015 | "authors": [
1016 | {
1017 | "name": "PHP-FIG",
1018 | "homepage": "http://www.php-fig.org/"
1019 | }
1020 | ],
1021 | "description": "Common interface for logging libraries",
1022 | "keywords": [
1023 | "log",
1024 | "psr",
1025 | "psr-3"
1026 | ],
1027 | "time": "2012-12-21 11:40:51"
1028 | },
1029 | {
1030 | "name": "satooshi/php-coveralls",
1031 | "version": "dev-master",
1032 | "source": {
1033 | "type": "git",
1034 | "url": "https://github.com/satooshi/php-coveralls.git",
1035 | "reference": "2fbf803803d179ab1082807308a67bbd5a760c70"
1036 | },
1037 | "dist": {
1038 | "type": "zip",
1039 | "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/2fbf803803d179ab1082807308a67bbd5a760c70",
1040 | "reference": "2fbf803803d179ab1082807308a67bbd5a760c70",
1041 | "shasum": ""
1042 | },
1043 | "require": {
1044 | "ext-json": "*",
1045 | "ext-simplexml": "*",
1046 | "guzzle/guzzle": ">=2.7",
1047 | "php": ">=5.3",
1048 | "psr/log": "1.0.0",
1049 | "symfony/config": ">=2.0",
1050 | "symfony/console": ">=2.0",
1051 | "symfony/stopwatch": ">=2.2",
1052 | "symfony/yaml": ">=2.0"
1053 | },
1054 | "require-dev": {
1055 | "apigen/apigen": "2.8.*@stable",
1056 | "pdepend/pdepend": "dev-master as 2.0.0",
1057 | "phpmd/phpmd": "dev-master",
1058 | "phpunit/php-invoker": ">=1.1.0,<1.2.0",
1059 | "phpunit/phpunit": "3.7.*@stable",
1060 | "sebastian/finder-facade": "dev-master",
1061 | "sebastian/phpcpd": "1.4.*@stable",
1062 | "squizlabs/php_codesniffer": "1.4.*@stable",
1063 | "theseer/fdomdocument": "dev-master"
1064 | },
1065 | "suggest": {
1066 | "symfony/http-kernel": "Allows Symfony integration"
1067 | },
1068 | "bin": [
1069 | "composer/bin/coveralls"
1070 | ],
1071 | "type": "library",
1072 | "extra": {
1073 | "branch-alias": {
1074 | "dev-master": "0.7-dev"
1075 | }
1076 | },
1077 | "autoload": {
1078 | "psr-0": {
1079 | "Satooshi\\Component": "src/",
1080 | "Satooshi\\Bundle": "src/"
1081 | }
1082 | },
1083 | "notification-url": "https://packagist.org/downloads/",
1084 | "license": [
1085 | "MIT"
1086 | ],
1087 | "authors": [
1088 | {
1089 | "name": "Kitamura Satoshi",
1090 | "email": "with.no.parachute@gmail.com",
1091 | "homepage": "https://www.facebook.com/satooshi.jp"
1092 | }
1093 | ],
1094 | "description": "PHP client library for Coveralls API",
1095 | "homepage": "https://github.com/satooshi/php-coveralls",
1096 | "keywords": [
1097 | "ci",
1098 | "coverage",
1099 | "github",
1100 | "test"
1101 | ],
1102 | "time": "2014-11-11 15:35:34"
1103 | },
1104 | {
1105 | "name": "sebastian/comparator",
1106 | "version": "1.2.0",
1107 | "source": {
1108 | "type": "git",
1109 | "url": "https://github.com/sebastianbergmann/comparator.git",
1110 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22"
1111 | },
1112 | "dist": {
1113 | "type": "zip",
1114 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/937efb279bd37a375bcadf584dec0726f84dbf22",
1115 | "reference": "937efb279bd37a375bcadf584dec0726f84dbf22",
1116 | "shasum": ""
1117 | },
1118 | "require": {
1119 | "php": ">=5.3.3",
1120 | "sebastian/diff": "~1.2",
1121 | "sebastian/exporter": "~1.2"
1122 | },
1123 | "require-dev": {
1124 | "phpunit/phpunit": "~4.4"
1125 | },
1126 | "type": "library",
1127 | "extra": {
1128 | "branch-alias": {
1129 | "dev-master": "1.2.x-dev"
1130 | }
1131 | },
1132 | "autoload": {
1133 | "classmap": [
1134 | "src/"
1135 | ]
1136 | },
1137 | "notification-url": "https://packagist.org/downloads/",
1138 | "license": [
1139 | "BSD-3-Clause"
1140 | ],
1141 | "authors": [
1142 | {
1143 | "name": "Jeff Welch",
1144 | "email": "whatthejeff@gmail.com"
1145 | },
1146 | {
1147 | "name": "Volker Dusch",
1148 | "email": "github@wallbash.com"
1149 | },
1150 | {
1151 | "name": "Bernhard Schussek",
1152 | "email": "bschussek@2bepublished.at"
1153 | },
1154 | {
1155 | "name": "Sebastian Bergmann",
1156 | "email": "sebastian@phpunit.de"
1157 | }
1158 | ],
1159 | "description": "Provides the functionality to compare PHP values for equality",
1160 | "homepage": "http://www.github.com/sebastianbergmann/comparator",
1161 | "keywords": [
1162 | "comparator",
1163 | "compare",
1164 | "equality"
1165 | ],
1166 | "time": "2015-07-26 15:48:44"
1167 | },
1168 | {
1169 | "name": "sebastian/diff",
1170 | "version": "1.3.0",
1171 | "source": {
1172 | "type": "git",
1173 | "url": "https://github.com/sebastianbergmann/diff.git",
1174 | "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3"
1175 | },
1176 | "dist": {
1177 | "type": "zip",
1178 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3",
1179 | "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3",
1180 | "shasum": ""
1181 | },
1182 | "require": {
1183 | "php": ">=5.3.3"
1184 | },
1185 | "require-dev": {
1186 | "phpunit/phpunit": "~4.2"
1187 | },
1188 | "type": "library",
1189 | "extra": {
1190 | "branch-alias": {
1191 | "dev-master": "1.3-dev"
1192 | }
1193 | },
1194 | "autoload": {
1195 | "classmap": [
1196 | "src/"
1197 | ]
1198 | },
1199 | "notification-url": "https://packagist.org/downloads/",
1200 | "license": [
1201 | "BSD-3-Clause"
1202 | ],
1203 | "authors": [
1204 | {
1205 | "name": "Kore Nordmann",
1206 | "email": "mail@kore-nordmann.de"
1207 | },
1208 | {
1209 | "name": "Sebastian Bergmann",
1210 | "email": "sebastian@phpunit.de"
1211 | }
1212 | ],
1213 | "description": "Diff implementation",
1214 | "homepage": "http://www.github.com/sebastianbergmann/diff",
1215 | "keywords": [
1216 | "diff"
1217 | ],
1218 | "time": "2015-02-22 15:13:53"
1219 | },
1220 | {
1221 | "name": "sebastian/environment",
1222 | "version": "1.3.2",
1223 | "source": {
1224 | "type": "git",
1225 | "url": "https://github.com/sebastianbergmann/environment.git",
1226 | "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44"
1227 | },
1228 | "dist": {
1229 | "type": "zip",
1230 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6324c907ce7a52478eeeaede764f48733ef5ae44",
1231 | "reference": "6324c907ce7a52478eeeaede764f48733ef5ae44",
1232 | "shasum": ""
1233 | },
1234 | "require": {
1235 | "php": ">=5.3.3"
1236 | },
1237 | "require-dev": {
1238 | "phpunit/phpunit": "~4.4"
1239 | },
1240 | "type": "library",
1241 | "extra": {
1242 | "branch-alias": {
1243 | "dev-master": "1.3.x-dev"
1244 | }
1245 | },
1246 | "autoload": {
1247 | "classmap": [
1248 | "src/"
1249 | ]
1250 | },
1251 | "notification-url": "https://packagist.org/downloads/",
1252 | "license": [
1253 | "BSD-3-Clause"
1254 | ],
1255 | "authors": [
1256 | {
1257 | "name": "Sebastian Bergmann",
1258 | "email": "sebastian@phpunit.de"
1259 | }
1260 | ],
1261 | "description": "Provides functionality to handle HHVM/PHP environments",
1262 | "homepage": "http://www.github.com/sebastianbergmann/environment",
1263 | "keywords": [
1264 | "Xdebug",
1265 | "environment",
1266 | "hhvm"
1267 | ],
1268 | "time": "2015-08-03 06:14:51"
1269 | },
1270 | {
1271 | "name": "sebastian/exporter",
1272 | "version": "1.2.1",
1273 | "source": {
1274 | "type": "git",
1275 | "url": "https://github.com/sebastianbergmann/exporter.git",
1276 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
1277 | },
1278 | "dist": {
1279 | "type": "zip",
1280 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
1281 | "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
1282 | "shasum": ""
1283 | },
1284 | "require": {
1285 | "php": ">=5.3.3",
1286 | "sebastian/recursion-context": "~1.0"
1287 | },
1288 | "require-dev": {
1289 | "phpunit/phpunit": "~4.4"
1290 | },
1291 | "type": "library",
1292 | "extra": {
1293 | "branch-alias": {
1294 | "dev-master": "1.2.x-dev"
1295 | }
1296 | },
1297 | "autoload": {
1298 | "classmap": [
1299 | "src/"
1300 | ]
1301 | },
1302 | "notification-url": "https://packagist.org/downloads/",
1303 | "license": [
1304 | "BSD-3-Clause"
1305 | ],
1306 | "authors": [
1307 | {
1308 | "name": "Jeff Welch",
1309 | "email": "whatthejeff@gmail.com"
1310 | },
1311 | {
1312 | "name": "Volker Dusch",
1313 | "email": "github@wallbash.com"
1314 | },
1315 | {
1316 | "name": "Bernhard Schussek",
1317 | "email": "bschussek@2bepublished.at"
1318 | },
1319 | {
1320 | "name": "Sebastian Bergmann",
1321 | "email": "sebastian@phpunit.de"
1322 | },
1323 | {
1324 | "name": "Adam Harvey",
1325 | "email": "aharvey@php.net"
1326 | }
1327 | ],
1328 | "description": "Provides the functionality to export PHP variables for visualization",
1329 | "homepage": "http://www.github.com/sebastianbergmann/exporter",
1330 | "keywords": [
1331 | "export",
1332 | "exporter"
1333 | ],
1334 | "time": "2015-06-21 07:55:53"
1335 | },
1336 | {
1337 | "name": "sebastian/global-state",
1338 | "version": "1.1.1",
1339 | "source": {
1340 | "type": "git",
1341 | "url": "https://github.com/sebastianbergmann/global-state.git",
1342 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
1343 | },
1344 | "dist": {
1345 | "type": "zip",
1346 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
1347 | "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
1348 | "shasum": ""
1349 | },
1350 | "require": {
1351 | "php": ">=5.3.3"
1352 | },
1353 | "require-dev": {
1354 | "phpunit/phpunit": "~4.2"
1355 | },
1356 | "suggest": {
1357 | "ext-uopz": "*"
1358 | },
1359 | "type": "library",
1360 | "extra": {
1361 | "branch-alias": {
1362 | "dev-master": "1.0-dev"
1363 | }
1364 | },
1365 | "autoload": {
1366 | "classmap": [
1367 | "src/"
1368 | ]
1369 | },
1370 | "notification-url": "https://packagist.org/downloads/",
1371 | "license": [
1372 | "BSD-3-Clause"
1373 | ],
1374 | "authors": [
1375 | {
1376 | "name": "Sebastian Bergmann",
1377 | "email": "sebastian@phpunit.de"
1378 | }
1379 | ],
1380 | "description": "Snapshotting of global state",
1381 | "homepage": "http://www.github.com/sebastianbergmann/global-state",
1382 | "keywords": [
1383 | "global state"
1384 | ],
1385 | "time": "2015-10-12 03:26:01"
1386 | },
1387 | {
1388 | "name": "sebastian/recursion-context",
1389 | "version": "1.0.1",
1390 | "source": {
1391 | "type": "git",
1392 | "url": "https://github.com/sebastianbergmann/recursion-context.git",
1393 | "reference": "994d4a811bafe801fb06dccbee797863ba2792ba"
1394 | },
1395 | "dist": {
1396 | "type": "zip",
1397 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/994d4a811bafe801fb06dccbee797863ba2792ba",
1398 | "reference": "994d4a811bafe801fb06dccbee797863ba2792ba",
1399 | "shasum": ""
1400 | },
1401 | "require": {
1402 | "php": ">=5.3.3"
1403 | },
1404 | "require-dev": {
1405 | "phpunit/phpunit": "~4.4"
1406 | },
1407 | "type": "library",
1408 | "extra": {
1409 | "branch-alias": {
1410 | "dev-master": "1.0.x-dev"
1411 | }
1412 | },
1413 | "autoload": {
1414 | "classmap": [
1415 | "src/"
1416 | ]
1417 | },
1418 | "notification-url": "https://packagist.org/downloads/",
1419 | "license": [
1420 | "BSD-3-Clause"
1421 | ],
1422 | "authors": [
1423 | {
1424 | "name": "Jeff Welch",
1425 | "email": "whatthejeff@gmail.com"
1426 | },
1427 | {
1428 | "name": "Sebastian Bergmann",
1429 | "email": "sebastian@phpunit.de"
1430 | },
1431 | {
1432 | "name": "Adam Harvey",
1433 | "email": "aharvey@php.net"
1434 | }
1435 | ],
1436 | "description": "Provides functionality to recursively process PHP variables",
1437 | "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
1438 | "time": "2015-06-21 08:04:50"
1439 | },
1440 | {
1441 | "name": "sebastian/version",
1442 | "version": "1.0.6",
1443 | "source": {
1444 | "type": "git",
1445 | "url": "https://github.com/sebastianbergmann/version.git",
1446 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
1447 | },
1448 | "dist": {
1449 | "type": "zip",
1450 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1451 | "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
1452 | "shasum": ""
1453 | },
1454 | "type": "library",
1455 | "autoload": {
1456 | "classmap": [
1457 | "src/"
1458 | ]
1459 | },
1460 | "notification-url": "https://packagist.org/downloads/",
1461 | "license": [
1462 | "BSD-3-Clause"
1463 | ],
1464 | "authors": [
1465 | {
1466 | "name": "Sebastian Bergmann",
1467 | "email": "sebastian@phpunit.de",
1468 | "role": "lead"
1469 | }
1470 | ],
1471 | "description": "Library that helps with managing the version number of Git-hosted PHP projects",
1472 | "homepage": "https://github.com/sebastianbergmann/version",
1473 | "time": "2015-06-21 13:59:46"
1474 | },
1475 | {
1476 | "name": "symfony/config",
1477 | "version": "v2.7.6",
1478 | "source": {
1479 | "type": "git",
1480 | "url": "https://github.com/symfony/config.git",
1481 | "reference": "831f88908b51b9ce945f5e6f402931d1ac544423"
1482 | },
1483 | "dist": {
1484 | "type": "zip",
1485 | "url": "https://api.github.com/repos/symfony/config/zipball/831f88908b51b9ce945f5e6f402931d1ac544423",
1486 | "reference": "831f88908b51b9ce945f5e6f402931d1ac544423",
1487 | "shasum": ""
1488 | },
1489 | "require": {
1490 | "php": ">=5.3.9",
1491 | "symfony/filesystem": "~2.3"
1492 | },
1493 | "type": "library",
1494 | "extra": {
1495 | "branch-alias": {
1496 | "dev-master": "2.7-dev"
1497 | }
1498 | },
1499 | "autoload": {
1500 | "psr-4": {
1501 | "Symfony\\Component\\Config\\": ""
1502 | }
1503 | },
1504 | "notification-url": "https://packagist.org/downloads/",
1505 | "license": [
1506 | "MIT"
1507 | ],
1508 | "authors": [
1509 | {
1510 | "name": "Fabien Potencier",
1511 | "email": "fabien@symfony.com"
1512 | },
1513 | {
1514 | "name": "Symfony Community",
1515 | "homepage": "https://symfony.com/contributors"
1516 | }
1517 | ],
1518 | "description": "Symfony Config Component",
1519 | "homepage": "https://symfony.com",
1520 | "time": "2015-10-11 09:39:48"
1521 | },
1522 | {
1523 | "name": "symfony/console",
1524 | "version": "v2.7.6",
1525 | "source": {
1526 | "type": "git",
1527 | "url": "https://github.com/symfony/console.git",
1528 | "reference": "5efd632294c8320ea52492db22292ff853a43766"
1529 | },
1530 | "dist": {
1531 | "type": "zip",
1532 | "url": "https://api.github.com/repos/symfony/console/zipball/5efd632294c8320ea52492db22292ff853a43766",
1533 | "reference": "5efd632294c8320ea52492db22292ff853a43766",
1534 | "shasum": ""
1535 | },
1536 | "require": {
1537 | "php": ">=5.3.9"
1538 | },
1539 | "require-dev": {
1540 | "psr/log": "~1.0",
1541 | "symfony/event-dispatcher": "~2.1",
1542 | "symfony/process": "~2.1"
1543 | },
1544 | "suggest": {
1545 | "psr/log": "For using the console logger",
1546 | "symfony/event-dispatcher": "",
1547 | "symfony/process": ""
1548 | },
1549 | "type": "library",
1550 | "extra": {
1551 | "branch-alias": {
1552 | "dev-master": "2.7-dev"
1553 | }
1554 | },
1555 | "autoload": {
1556 | "psr-4": {
1557 | "Symfony\\Component\\Console\\": ""
1558 | }
1559 | },
1560 | "notification-url": "https://packagist.org/downloads/",
1561 | "license": [
1562 | "MIT"
1563 | ],
1564 | "authors": [
1565 | {
1566 | "name": "Fabien Potencier",
1567 | "email": "fabien@symfony.com"
1568 | },
1569 | {
1570 | "name": "Symfony Community",
1571 | "homepage": "https://symfony.com/contributors"
1572 | }
1573 | ],
1574 | "description": "Symfony Console Component",
1575 | "homepage": "https://symfony.com",
1576 | "time": "2015-10-20 14:38:46"
1577 | },
1578 | {
1579 | "name": "symfony/event-dispatcher",
1580 | "version": "v2.7.6",
1581 | "source": {
1582 | "type": "git",
1583 | "url": "https://github.com/symfony/event-dispatcher.git",
1584 | "reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8"
1585 | },
1586 | "dist": {
1587 | "type": "zip",
1588 | "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87a5db5ea887763fa3a31a5471b512ff1596d9b8",
1589 | "reference": "87a5db5ea887763fa3a31a5471b512ff1596d9b8",
1590 | "shasum": ""
1591 | },
1592 | "require": {
1593 | "php": ">=5.3.9"
1594 | },
1595 | "require-dev": {
1596 | "psr/log": "~1.0",
1597 | "symfony/config": "~2.0,>=2.0.5",
1598 | "symfony/dependency-injection": "~2.6",
1599 | "symfony/expression-language": "~2.6",
1600 | "symfony/stopwatch": "~2.3"
1601 | },
1602 | "suggest": {
1603 | "symfony/dependency-injection": "",
1604 | "symfony/http-kernel": ""
1605 | },
1606 | "type": "library",
1607 | "extra": {
1608 | "branch-alias": {
1609 | "dev-master": "2.7-dev"
1610 | }
1611 | },
1612 | "autoload": {
1613 | "psr-4": {
1614 | "Symfony\\Component\\EventDispatcher\\": ""
1615 | }
1616 | },
1617 | "notification-url": "https://packagist.org/downloads/",
1618 | "license": [
1619 | "MIT"
1620 | ],
1621 | "authors": [
1622 | {
1623 | "name": "Fabien Potencier",
1624 | "email": "fabien@symfony.com"
1625 | },
1626 | {
1627 | "name": "Symfony Community",
1628 | "homepage": "https://symfony.com/contributors"
1629 | }
1630 | ],
1631 | "description": "Symfony EventDispatcher Component",
1632 | "homepage": "https://symfony.com",
1633 | "time": "2015-10-11 09:39:48"
1634 | },
1635 | {
1636 | "name": "symfony/filesystem",
1637 | "version": "v2.7.6",
1638 | "source": {
1639 | "type": "git",
1640 | "url": "https://github.com/symfony/filesystem.git",
1641 | "reference": "56fd6df73be859323ff97418d97edc1d756df6df"
1642 | },
1643 | "dist": {
1644 | "type": "zip",
1645 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/56fd6df73be859323ff97418d97edc1d756df6df",
1646 | "reference": "56fd6df73be859323ff97418d97edc1d756df6df",
1647 | "shasum": ""
1648 | },
1649 | "require": {
1650 | "php": ">=5.3.9"
1651 | },
1652 | "type": "library",
1653 | "extra": {
1654 | "branch-alias": {
1655 | "dev-master": "2.7-dev"
1656 | }
1657 | },
1658 | "autoload": {
1659 | "psr-4": {
1660 | "Symfony\\Component\\Filesystem\\": ""
1661 | }
1662 | },
1663 | "notification-url": "https://packagist.org/downloads/",
1664 | "license": [
1665 | "MIT"
1666 | ],
1667 | "authors": [
1668 | {
1669 | "name": "Fabien Potencier",
1670 | "email": "fabien@symfony.com"
1671 | },
1672 | {
1673 | "name": "Symfony Community",
1674 | "homepage": "https://symfony.com/contributors"
1675 | }
1676 | ],
1677 | "description": "Symfony Filesystem Component",
1678 | "homepage": "https://symfony.com",
1679 | "time": "2015-10-18 20:23:18"
1680 | },
1681 | {
1682 | "name": "symfony/stopwatch",
1683 | "version": "v2.7.6",
1684 | "source": {
1685 | "type": "git",
1686 | "url": "https://github.com/symfony/stopwatch.git",
1687 | "reference": "f8ab957c17e4b85a73c4df03bdf94ee597f2bd55"
1688 | },
1689 | "dist": {
1690 | "type": "zip",
1691 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/f8ab957c17e4b85a73c4df03bdf94ee597f2bd55",
1692 | "reference": "f8ab957c17e4b85a73c4df03bdf94ee597f2bd55",
1693 | "shasum": ""
1694 | },
1695 | "require": {
1696 | "php": ">=5.3.9"
1697 | },
1698 | "type": "library",
1699 | "extra": {
1700 | "branch-alias": {
1701 | "dev-master": "2.7-dev"
1702 | }
1703 | },
1704 | "autoload": {
1705 | "psr-4": {
1706 | "Symfony\\Component\\Stopwatch\\": ""
1707 | }
1708 | },
1709 | "notification-url": "https://packagist.org/downloads/",
1710 | "license": [
1711 | "MIT"
1712 | ],
1713 | "authors": [
1714 | {
1715 | "name": "Fabien Potencier",
1716 | "email": "fabien@symfony.com"
1717 | },
1718 | {
1719 | "name": "Symfony Community",
1720 | "homepage": "https://symfony.com/contributors"
1721 | }
1722 | ],
1723 | "description": "Symfony Stopwatch Component",
1724 | "homepage": "https://symfony.com",
1725 | "time": "2015-10-12 12:42:24"
1726 | },
1727 | {
1728 | "name": "symfony/yaml",
1729 | "version": "v2.7.6",
1730 | "source": {
1731 | "type": "git",
1732 | "url": "https://github.com/symfony/yaml.git",
1733 | "reference": "eca9019c88fbe250164affd107bc8057771f3f4d"
1734 | },
1735 | "dist": {
1736 | "type": "zip",
1737 | "url": "https://api.github.com/repos/symfony/yaml/zipball/eca9019c88fbe250164affd107bc8057771f3f4d",
1738 | "reference": "eca9019c88fbe250164affd107bc8057771f3f4d",
1739 | "shasum": ""
1740 | },
1741 | "require": {
1742 | "php": ">=5.3.9"
1743 | },
1744 | "type": "library",
1745 | "extra": {
1746 | "branch-alias": {
1747 | "dev-master": "2.7-dev"
1748 | }
1749 | },
1750 | "autoload": {
1751 | "psr-4": {
1752 | "Symfony\\Component\\Yaml\\": ""
1753 | }
1754 | },
1755 | "notification-url": "https://packagist.org/downloads/",
1756 | "license": [
1757 | "MIT"
1758 | ],
1759 | "authors": [
1760 | {
1761 | "name": "Fabien Potencier",
1762 | "email": "fabien@symfony.com"
1763 | },
1764 | {
1765 | "name": "Symfony Community",
1766 | "homepage": "https://symfony.com/contributors"
1767 | }
1768 | ],
1769 | "description": "Symfony Yaml Component",
1770 | "homepage": "https://symfony.com",
1771 | "time": "2015-10-11 09:39:48"
1772 | }
1773 | ],
1774 | "aliases": [],
1775 | "minimum-stability": "stable",
1776 | "stability-flags": {
1777 | "satooshi/php-coveralls": 20
1778 | },
1779 | "prefer-stable": false,
1780 | "prefer-lowest": false,
1781 | "platform": {
1782 | "php": ">=5.4.4"
1783 | },
1784 | "platform-dev": []
1785 | }
1786 |
--------------------------------------------------------------------------------
/composer.phar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ortic/css2scss/30274f599ac26f2e1fe24f1de49704742d08b9de/composer.phar
--------------------------------------------------------------------------------
/example.php:
--------------------------------------------------------------------------------
1 | getScss();
13 |
--------------------------------------------------------------------------------
/phpunit.php:
--------------------------------------------------------------------------------
1 |
2 |
12 |
13 |
14 | ./tests/
15 |
16 |
17 |
18 |
19 | ./src/
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/Css2Scss.php:
--------------------------------------------------------------------------------
1 | cssContent = $cssContent;
57 | $this->parser = new \CssParser($this->cssContent);
58 | }
59 |
60 | /**
61 | * Iterates through all tokens and extracts the values into variables
62 | */
63 | protected function extractVariables()
64 | {
65 | $properties = ['color', 'font-family'];
66 | foreach ($properties as $property) {
67 | $this->variables[$property] = [];
68 | }
69 |
70 | foreach ($this->tokens as $token) {
71 | if ($token instanceof \CssRulesetDeclarationToken && in_array($token->Property, $properties)) {
72 | if (!array_key_exists($token->Value, $this->variables[$token->Property])) {
73 | $this->variables[$token->Property][$token->Value] = $token->Property . '_' . (count($this->variables[$token->Property]) + 1);
74 |
75 | }
76 | $token->Value = '$' . $this->variables[$token->Property][$token->Value];
77 | }
78 | }
79 | }
80 |
81 | /**
82 | * Returns a string containing all variables to be printed in the output
83 | *
84 | * @return string
85 | */
86 | protected function getVariables()
87 | {
88 | $return = '';
89 | foreach ($this->variables as $properties) {
90 | foreach ($properties as $variable => $property) {
91 | $return .= "\${$property}: {$variable};\n";
92 | }
93 | }
94 | $return .= "\n";
95 | return $return;
96 | }
97 |
98 | /**
99 | * Returns a string containing the SCSS content matching the CSS input
100 | * @return string
101 | */
102 | public function getScss($extractVariables = false)
103 | {
104 | $this->tokens = $this->parser->getTokens();
105 |
106 | // extract variables
107 | if ($extractVariables) {
108 | $this->extractVariables();
109 | }
110 |
111 | $this->buildNestedTree();
112 |
113 | $return = '';
114 |
115 | // print variables
116 | if ($extractVariables) {
117 | $return .= $this->getVariables();
118 | }
119 |
120 | foreach ($this->scssTree as $node) {
121 | // @TODO this format method shouldn't be in this class..
122 | $return .= $this->ruleSetList->formatTokenAsScss($node) . "\n";
123 | }
124 |
125 | $return .= $this->ruleSetList->scssify();
126 |
127 | return $return;
128 | }
129 |
130 | /**
131 | * Build a nested tree based on the flat CSS tokens
132 | */
133 | protected function buildNestedTree()
134 | {
135 | // this variable is true, if we're within a ruleset, e.g. p { .. here .. }
136 | // we have to normalize them
137 | $withinRulset = false;
138 | $ruleSet = null;
139 | $this->ruleSetList = new ScssRuleList();
140 |
141 | foreach ($this->tokens as $token) {
142 | // we have to skip some tokens, their information is redundant
143 | if ($token instanceof \CssAtMediaStartToken ||
144 | $token instanceof \CssAtMediaEndToken
145 | ) {
146 | continue;
147 | }
148 |
149 | // we have to build a hierarchy with CssRulesetStartToken, CssRulesetEndToken
150 | if ($token instanceof \CssRulesetStartToken) {
151 | $withinRulset = true;
152 | $ruleSet = new ScssRule($token->Selectors);
153 | } elseif ($token instanceof \CssRulesetEndToken) {
154 | $withinRulset = false;
155 | if ($ruleSet) {
156 | $this->ruleSetList->addRule($ruleSet);
157 | }
158 | $ruleSet = null;
159 | } else {
160 | // as long as we're in a ruleset, we're adding all token to a custom array
161 | // this will be lessified once we've found CssRulesetEndToken and then added
162 | // to the actual $lessTree variable
163 | if ($withinRulset) {
164 | $ruleSet->addToken($token);
165 | } else {
166 | $this->scssTree[] = $token;
167 | }
168 | }
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/tokens/ScssRule.php:
--------------------------------------------------------------------------------
1 | selectors = $selectors;
20 | }
21 |
22 | /**
23 | * Add new node to rule
24 | * @param $token
25 | */
26 | public function addToken($token)
27 | {
28 | $this->tokens[] = $token;
29 | }
30 |
31 | /**
32 | * Returns the list of selectors (e.g. #logo img)
33 | * @return array
34 | */
35 | public function getSelectors()
36 | {
37 | return $this->selectors;
38 | }
39 |
40 | /**
41 | * Returns a list of tokens/nodes for the current selector
42 | * @return array
43 | */
44 | public function getTokens()
45 | {
46 | return $this->tokens;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/tokens/ScssRuleList.php:
--------------------------------------------------------------------------------
1 | list[] = $rule;
20 | }
21 |
22 | /**
23 | * Build and returns a tree for the CSS input
24 | * @return array
25 | */
26 | protected function getTree()
27 | {
28 | $output = array();
29 |
30 | foreach ($this->list as $ruleSet) {
31 | $selectors = $ruleSet->getSelectors();
32 |
33 | foreach ($ruleSet->getTokens() as $token) {
34 | if(is_object($token) && get_class($token) === 'CssCommentToken') continue;
35 |
36 | $this->parseTreeNode($output, $selectors, $token);
37 | }
38 | }
39 | return $output;
40 | }
41 |
42 | /**
43 | * Add support for direct descendants operator by aligning the spaces properly.
44 | * the code below supports "html >p" since we split by spaces. A selector "html > p" would cause an
45 | * additional tree level, we therefore normalize them with the two lines below.
46 | *
47 | * @param string $selector
48 | * @return string
49 | */
50 | protected function parseDirectDescendants($selector)
51 | {
52 | $selector = str_replace('> ', '>', $selector);
53 | $selector = str_replace('>', ' >', $selector);
54 | return $selector;
55 | }
56 |
57 | /**
58 | * Support for pseudo classes by adding a space before ":" and also "&" to let scss know that there
59 | * shouldn't be a space when concatenating the nested selectors to a single css rule. We have to
60 | * ignore every colon if it's wrapped by :not(...) as we don't nest this in SCSS.
61 | *
62 | * @param string $selector
63 | * @return string
64 | */
65 | protected function parsePseudoClasses($selector)
66 | {
67 | $nestedPseudo = false;
68 | $lastCharacterColon = false;
69 | $selectorOut = '';
70 | for ($i = 0; $i < strlen($selector); $i++) {
71 | $c = $selector[$i];
72 |
73 | // Don't parse anything between (..) and [..]
74 | $nestedPseudo = ($c === '(' || $c === '[') || $nestedPseudo;
75 | $nestedPseudo = !($c === ')' || $c === ']') && $nestedPseudo;
76 |
77 | if ($nestedPseudo === false && $c === ':' && $lastCharacterColon === false) {
78 | $selectorOut .= ' &';
79 | $lastCharacterColon = true;
80 | }
81 | else {
82 | $lastCharacterColon = false;
83 | }
84 |
85 | $selectorOut .= $c;
86 | }
87 | return $selectorOut;
88 | }
89 |
90 | /**
91 | * Parse CSS input part into a SCSS node
92 | * @param $output
93 | * @param $selectors
94 | * @param $token
95 | */
96 | protected function parseTreeNode(&$output, $selectors, $token)
97 | {
98 | foreach ($token->MediaTypes as $mediaType) {
99 | // make sure we're aware of our media type
100 | if (!array_key_exists($mediaType, $output)) {
101 | $output[$mediaType] = array();
102 | }
103 |
104 | foreach ($selectors as $selector) {
105 | // add declaration token to output for each selector
106 | $currentNode = &$output[$mediaType];
107 |
108 | $selector = $this->parseDirectDescendants($selector);
109 | $selector = $this->parsePseudoClasses($selector);
110 |
111 | // selectors like "html body" must be split into an array so we can
112 | // easily nest them
113 | $selectorPath = preg_split('[ ]', $selector, -1, PREG_SPLIT_NO_EMPTY);
114 | foreach ($selectorPath as $selectorPathItem) {
115 | if (!array_key_exists($selectorPathItem, $currentNode)) {
116 | $currentNode[$selectorPathItem] = array();
117 | }
118 | $currentNode = &$currentNode[$selectorPathItem];
119 | }
120 |
121 | $currentNode['@rules'][] = $this->formatTokenAsScss($token);
122 | }
123 | }
124 | }
125 |
126 | /**
127 | * Format SCSS nodes in a nicer way with indentation and proper brackets
128 | * @param $token
129 | * @param int $level
130 | * @return string
131 | */
132 | public function formatTokenAsScss(\aCssToken $token, $level = 0)
133 | {
134 | $indentation = str_repeat("\t", $level);
135 |
136 | if ($token instanceof \CssRulesetDeclarationToken) {
137 | return $indentation . $token->Property . ": " . $token->Value . ($token->IsImportant ? " !important" : "") . ($token->IsLast ? "" : ";");
138 | } elseif ($token instanceof \CssAtKeyframesStartToken) {
139 | return $indentation . "@" . $token->AtRuleName . " " . $token->Name . " {";
140 | } elseif ($token instanceof \CssAtKeyframesRulesetStartToken) {
141 | return $indentation . "\t" . implode(",", $token->Selectors) . " {";
142 | } elseif ($token instanceof \CssAtKeyframesRulesetEndToken) {
143 | return $indentation . "\t" . "}";
144 | } elseif ($token instanceof \CssAtKeyframesRulesetDeclarationToken) {
145 | return $indentation . "\t\t" . $token->Property . ": " . $token->Value . ($token->IsImportant ? " !important" : "") . ($token->IsLast ? "" : ";");
146 | } elseif ($token instanceof \CssAtCharsetToken) {
147 | return $indentation . "@charset " . $token->Charset . ";";
148 | } elseif ($token instanceof \CssAtFontFaceStartToken) {
149 | return "@font-face {";
150 | } elseif ($token instanceof \CssAtFontFaceDeclarationToken) {
151 | return $indentation . "\t" . $token->Property . ": " . $token->Value . ($token->IsImportant ? " !important" : "") . ($token->IsLast ? "" : ";");
152 | } else {
153 | return $indentation . $token;
154 | }
155 | }
156 |
157 | protected function formatAsScss($selector, $level = 0)
158 | {
159 | $return = '';
160 | $indentation = str_repeat("\t", $level);
161 | foreach ($selector as $nodeKey => $node) {
162 | $return .= $indentation . "{$nodeKey} {\n";
163 |
164 | foreach ($node as $subNodeKey => $subNodes) {
165 | if ($subNodeKey === '@rules') {
166 | foreach ($subNodes as $subNode) {
167 | $return .= $indentation . "\t" . $subNode . "\n";
168 | }
169 | } else {
170 | $return .= $this->formatAsScss(array($subNodeKey => $subNodes), $level + 1);
171 | }
172 | }
173 |
174 | $return .= $indentation . "}\n";
175 |
176 | }
177 | return $return;
178 | }
179 |
180 | public function scssify()
181 | {
182 | $tree = $this->getTree();
183 | $return = '';
184 |
185 | foreach ($tree as $mediaType => $node) {
186 | if ($mediaType == 'all') {
187 | $return .= $this->formatAsScss($node);
188 | } else {
189 | $return .= "@media {$mediaType} {\n";
190 | $return .= $this->formatAsScss($node, 1);
191 | $return .= "}\n";
192 | }
193 | }
194 |
195 | return $return;
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/tests/Css2ScssTest.php:
--------------------------------------------------------------------------------
1 | p { font-size: 12px; }', "html {\n\t>p {\n\t\tfont-size: 12px;\n\t}\n}\n", false),
19 | array('html> p { font-size: 12px; }', "html {\n\t>p {\n\t\tfont-size: 12px;\n\t}\n}\n", false),
20 | array('html>p { font-size: 12px; }', "html {\n\t>p {\n\t\tfont-size: 12px;\n\t}\n}\n", false),
21 | array('html, body { margin: 0; }', "html {\n\tmargin: 0;\n}\nbody {\n\tmargin: 0;\n}\n", false),
22 | array('a:hover { text-decoration: none; }', "a {\n\t&:hover {\n\t\ttext-decoration: none;\n\t}\n}\n", false),
23 | array('button::-moz-focus-inner { border: 0; }', "button {\n\t&::-moz-focus-inner {\n\t\tborder: 0;\n\t}\n}\n", false),
24 | array('a[href^="javascript:"]:after { border: 0; }', "a[href^=\"javascript:\"] {\n\t&:after {\n\t\tborder: 0;\n\t}\n}\n", false),
25 | array('a { color: white; }', "\$color_1: white;\n\na {\n\tcolor: \$color_1;\n}\n", true),
26 | );
27 | }
28 |
29 | /**
30 | * @dataProvider providerSnippets
31 | */
32 | public function testSnippets($css, $scss, $extractVariables)
33 | {
34 | $css2scssParser = new Ortic\Css2Scss\Css2Scss($css);
35 | $scssOutput = $css2scssParser->getScss($extractVariables);
36 |
37 | $scssOutput = $this->normalizeLineEndings($scssOutput);
38 | $scssContent = $this->normalizeLineEndings($scss);
39 |
40 | $this->assertEquals($scssOutput, $scssContent);
41 | }
42 |
43 | public function testParseSimpleFile()
44 | {
45 | $cssContent = <<getScss();
130 |
131 | $scssOutput = $this->normalizeLineEndings($scssOutput);
132 | $scssContent = $this->normalizeLineEndings($scssContent);
133 |
134 | $this->assertEquals($scssOutput, $scssContent);
135 | }
136 | }
137 |
--------------------------------------------------------------------------------