Subiendo proyecto completo sin restricciones de git ignore
This commit is contained in:
1
vendor/sabberworm/php-css-parser/.gitignore
vendored
Normal file
1
vendor/sabberworm/php-css-parser/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
vendor/
|
||||
22
vendor/sabberworm/php-css-parser/.travis.yml
vendored
Normal file
22
vendor/sabberworm/php-css-parser/.travis.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
language: php
|
||||
php:
|
||||
- "5.4"
|
||||
- "5.5"
|
||||
- "5.6"
|
||||
- "7.0"
|
||||
- "7.1"
|
||||
- "7.2"
|
||||
- "7.3"
|
||||
- hhvm
|
||||
sudo: false
|
||||
dist: trusty
|
||||
matrix:
|
||||
include:
|
||||
-
|
||||
php: "5.3"
|
||||
dist: precise
|
||||
sudo: false
|
||||
before_script: rm composer.lock && composer install
|
||||
script: ./vendor/bin/phpunit --coverage-clover build/coverage/xml
|
||||
after_script: ./vendor/bin/codacycoverage clover build/coverage/xml
|
||||
|
||||
224
vendor/sabberworm/php-css-parser/CHANGELOG.md
vendored
Normal file
224
vendor/sabberworm/php-css-parser/CHANGELOG.md
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
# Revision History
|
||||
|
||||
## 8.0
|
||||
|
||||
### 8.0.0 (2016-06-30)
|
||||
|
||||
* Store source CSS line numbers in tokens and parsing exceptions.
|
||||
* *No deprecations*
|
||||
|
||||
#### Backwards-incompatible changes
|
||||
|
||||
* Unrecoverable parser errors throw an exception of type `Sabberworm\CSS\Parsing\SourceException` instead of `\Exception`.
|
||||
|
||||
### 8.1.0 (2016-07-19)
|
||||
|
||||
* Comments are no longer silently ignored but stored with the object with which they appear (no render support, though). Thanks to @FMCorz.
|
||||
* The IE hacks using `\0` and `\9` can now be parsed (and rendered) in lenient mode. Thanks (again) to @FMCorz.
|
||||
* Media queries with or without spaces before the query are parsed. Still no *real* parsing support, though. Sorry…
|
||||
* PHPUnit is now listed as a dev-dependency in composer.json.
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 8.2.0 (2018-07-13)
|
||||
|
||||
* Support parsing `calc()`, thanks to @raxbg.
|
||||
* Support parsing grid-lines, again thanks to @raxbg.
|
||||
* Support parsing legacy IE filters (`progid:`) in lenient mode, thanks to @FMCorz
|
||||
* Performance improvements parsing large files, again thanks to @FMCorz
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 8.3.0 (2019-02-22)
|
||||
|
||||
* Refactor parsing logic to mostly reside in the class files whose data structure is to be parsed (this should eventually allow us to unit-test specific parts of the parsing logic individually).
|
||||
* Fix error in parsing `calc` expessions when the first operand is a negative number, thanks to @raxbg.
|
||||
* Support parsing CSS4 colors in hex notation with alpha values, thanks to @raxbg.
|
||||
* Swallow more errors in lenient mode, thanks to @raxbg.
|
||||
* Allow specifying arbitrary strings to output before and after declaration blocks, thanks to @westonruter.
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
## 7.0
|
||||
|
||||
### 7.0.0 (2015-08-24)
|
||||
|
||||
* Compatibility with PHP 7. Well timed, eh?
|
||||
* *No deprecations*
|
||||
|
||||
#### Backwards-incompatible changes
|
||||
|
||||
* The `Sabberworm\CSS\Value\String` class has been renamed to `Sabberworm\CSS\Value\CSSString`.
|
||||
|
||||
### 7.0.1 (2015-12-25)
|
||||
|
||||
* No more suppressed `E_NOTICE`
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 7.0.2 (2016-02-11)
|
||||
|
||||
* 150 time performance boost thanks to @[ossinkine](https://github.com/ossinkine)
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 7.0.3 (2016-04-27)
|
||||
|
||||
* Fixed parsing empty CSS when multibyte is off
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
## 6.0
|
||||
|
||||
### 6.0.0 (2014-07-03)
|
||||
|
||||
* Format output using Sabberworm\CSS\OutputFormat
|
||||
* *No backwards-incompatible changes*
|
||||
|
||||
#### Deprecations
|
||||
|
||||
* The parse() method replaces __toString with an optional argument (instance of the OutputFormat class)
|
||||
|
||||
### 6.0.1 (2015-08-24)
|
||||
|
||||
* Remove some declarations in interfaces incompatible with PHP 5.3 (< 5.3.9)
|
||||
* *No deprecations*
|
||||
|
||||
## 5.0
|
||||
|
||||
### 5.0.0 (2013-03-20)
|
||||
|
||||
* Correctly parse all known CSS 3 units (including Hz and kHz).
|
||||
* Output RGB colors in short (#aaa or #ababab) notation
|
||||
* Be case-insensitive when parsing identifiers.
|
||||
* *No deprecations*
|
||||
|
||||
#### Backwards-incompatible changes
|
||||
|
||||
* `Sabberworm\CSS\Value\Color`’s `__toString` method overrides `CSSList`’s to maybe return something other than `type(value, …)` (see above).
|
||||
|
||||
### 5.0.1 (2013-03-20)
|
||||
|
||||
* Internal cleanup
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.0.2 (2013-03-21)
|
||||
|
||||
* CHANGELOG.md file added to distribution
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.0.3 (2013-03-21)
|
||||
|
||||
* More size units recognized
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.0.4 (2013-03-21)
|
||||
|
||||
* Don’t output floats with locale-aware separator chars
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.0.5 (2013-04-17)
|
||||
|
||||
* Initial support for lenient parsing (setting this parser option will catch some exceptions internally and recover the parser’s state as neatly as possible).
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.0.6 (2013-05-31)
|
||||
|
||||
* Fix broken unit test
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.0.7 (2013-08-04)
|
||||
|
||||
* Fix broken decimal point output optimization
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.0.8 (2013-08-15)
|
||||
|
||||
* Make default settings’ multibyte parsing option dependent on whether or not the mbstring extension is actually installed.
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.1.0 (2013-10-24)
|
||||
|
||||
* Performance enhancements by Michael M Slusarz
|
||||
* More rescue entry points for lenient parsing (unexpected tokens between declaration blocks and unclosed comments)
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.1.1 (2013-10-28)
|
||||
|
||||
* Updated CHANGELOG.md to reflect changes since 5.0.4
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.1.2 (2013-10-30)
|
||||
|
||||
* Remove the use of consumeUntil in comment parsing. This makes it possible to parse comments such as `/** Perfectly valid **/`
|
||||
* Add fr relative size unit
|
||||
* Fix some issues with HHVM
|
||||
* *No backwards-incompatible changes*
|
||||
* *No deprecations*
|
||||
|
||||
### 5.2.0 (2014-06-30)
|
||||
|
||||
* Support removing a selector from a declaration block using `$oBlock->removeSelector($mSelector)`
|
||||
* Introduce a specialized exception (Sabberworm\CSS\Parsing\OuputException) for exceptions during output rendering
|
||||
|
||||
* *No deprecations*
|
||||
|
||||
#### Backwards-incompatible changes
|
||||
|
||||
* Outputting a declaration block that has no selectors throws an OuputException instead of outputting an invalid ` {…}` into the CSS document.
|
||||
|
||||
## 4.0
|
||||
|
||||
### 4.0.0 (2013-03-19)
|
||||
|
||||
* Support for more @-rules
|
||||
* Generic interface `Sabberworm\CSS\Property\AtRule`, implemented by all @-rule classes
|
||||
* *No deprecations*
|
||||
|
||||
#### Backwards-incompatible changes
|
||||
|
||||
* `Sabberworm\CSS\RuleSet\AtRule` renamed to `Sabberworm\CSS\RuleSet\AtRuleSet`
|
||||
* `Sabberworm\CSS\CSSList\MediaQuery` renamed to `Sabberworm\CSS\RuleSet\CSSList\AtRuleBlockList` with differing semantics and API (which also works for other block-list-based @-rules like `@supports`).
|
||||
|
||||
## 3.0
|
||||
|
||||
### 3.0.0 (2013-03-06)
|
||||
|
||||
* Support for lenient parsing (on by default)
|
||||
* *No deprecations*
|
||||
|
||||
#### Backwards-incompatible changes
|
||||
|
||||
* All properties (like whether or not to use `mb_`-functions, which default charset to use and – new – whether or not to be forgiving when parsing) are now encapsulated in an instance of `Sabberworm\CSS\Settings` which can be passed as the second argument to `Sabberworm\CSS\Parser->__construct()`.
|
||||
* Specifying a charset as the second argument to `Sabberworm\CSS\Parser->__construct()` is no longer supported. Use `Sabberworm\CSS\Settings::create()->withDefaultCharset('some-charset')` instead.
|
||||
* Setting `Sabberworm\CSS\Parser->bUseMbFunctions` has no effect. Use `Sabberworm\CSS\Settings::create()->withMultibyteSupport(true/false)` instead.
|
||||
* `Sabberworm\CSS\Parser->parse()` may throw a `Sabberworm\CSS\Parsing\UnexpectedTokenException` when in strict parsing mode.
|
||||
|
||||
## 2.0
|
||||
|
||||
### 2.0.0 (2013-01-29)
|
||||
|
||||
* Allow multiple rules of the same type per rule set
|
||||
|
||||
#### Backwards-incompatible changes
|
||||
|
||||
* `Sabberworm\CSS\RuleSet->getRules()` returns an index-based array instead of an associative array. Use `Sabberworm\CSS\RuleSet->getRulesAssoc()` (which eliminates duplicate rules and lets the later rule of the same name win).
|
||||
* `Sabberworm\CSS\RuleSet->removeRule()` works as it did before except when passed an instance of `Sabberworm\CSS\Rule\Rule`, in which case it would only remove the exact rule given instead of all the rules of the same type. To get the old behaviour, use `Sabberworm\CSS\RuleSet->removeRule($oRule->getRule()`;
|
||||
|
||||
## 1.0
|
||||
|
||||
Initial release of a stable public API.
|
||||
|
||||
## 0.9
|
||||
|
||||
Last version not to use PSR-0 project organization semantics.
|
||||
2310
vendor/sabberworm/php-css-parser/Doxyfile
vendored
Normal file
2310
vendor/sabberworm/php-css-parser/Doxyfile
vendored
Normal file
File diff suppressed because it is too large
Load Diff
642
vendor/sabberworm/php-css-parser/README.md
vendored
Normal file
642
vendor/sabberworm/php-css-parser/README.md
vendored
Normal file
@@ -0,0 +1,642 @@
|
||||
PHP CSS Parser
|
||||
--------------
|
||||
|
||||
[](https://travis-ci.org/sabberworm/PHP-CSS-Parser) [](http://hhvm.h4cc.de/package/sabberworm/php-css-parser)
|
||||
|
||||
A Parser for CSS Files written in PHP. Allows extraction of CSS files into a data structure, manipulation of said structure and output as (optimized) CSS.
|
||||
|
||||
## Usage
|
||||
|
||||
### Installation using composer
|
||||
|
||||
Add php-css-parser to your composer.json
|
||||
|
||||
```json
|
||||
{
|
||||
"require": {
|
||||
"sabberworm/php-css-parser": "*"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Extraction
|
||||
|
||||
To use the CSS Parser, create a new instance. The constructor takes the following form:
|
||||
|
||||
```php
|
||||
new Sabberworm\CSS\Parser($sText);
|
||||
```
|
||||
|
||||
To read a file, for example, you’d do the following:
|
||||
|
||||
```php
|
||||
$oCssParser = new Sabberworm\CSS\Parser(file_get_contents('somefile.css'));
|
||||
$oCssDocument = $oCssParser->parse();
|
||||
```
|
||||
|
||||
The resulting CSS document structure can be manipulated prior to being output.
|
||||
|
||||
### Options
|
||||
|
||||
#### Charset
|
||||
|
||||
The charset option is used only if no @charset declaration is found in the CSS file. UTF-8 is the default, so you won’t have to create a settings object at all if you don’t intend to change that.
|
||||
|
||||
```php
|
||||
$oSettings = Sabberworm\CSS\Settings::create()->withDefaultCharset('windows-1252');
|
||||
new Sabberworm\CSS\Parser($sText, $oSettings);
|
||||
```
|
||||
|
||||
#### Strict parsing
|
||||
|
||||
To have the parser choke on invalid rules, supply a thusly configured Sabberworm\CSS\Settings object:
|
||||
|
||||
```php
|
||||
$oCssParser = new Sabberworm\CSS\Parser(file_get_contents('somefile.css'), Sabberworm\CSS\Settings::create()->beStrict());
|
||||
```
|
||||
|
||||
#### Disable multibyte functions
|
||||
|
||||
To achieve faster parsing, you can choose to have PHP-CSS-Parser use regular string functions instead of `mb_*` functions. This should work fine in most cases, even for UTF-8 files, as all the multibyte characters are in string literals. Still it’s not recommended to use this with input you have no control over as it’s not thoroughly covered by test cases.
|
||||
|
||||
```php
|
||||
$oSettings = Sabberworm\CSS\Settings::create()->withMultibyteSupport(false);
|
||||
new Sabberworm\CSS\Parser($sText, $oSettings);
|
||||
```
|
||||
|
||||
### Manipulation
|
||||
|
||||
The resulting data structure consists mainly of five basic types: `CSSList`, `RuleSet`, `Rule`, `Selector` and `Value`. There are two additional types used: `Import` and `Charset` which you won’t use often.
|
||||
|
||||
#### CSSList
|
||||
|
||||
`CSSList` represents a generic CSS container, most likely containing declaration blocks (rule sets with a selector) but it may also contain at-rules, charset declarations, etc. `CSSList` has the following concrete subtypes:
|
||||
|
||||
* `Document` – representing the root of a CSS file.
|
||||
* `MediaQuery` – represents a subsection of a CSSList that only applies to a output device matching the contained media query.
|
||||
|
||||
To access the items stored in a `CSSList` – like the document you got back when calling `$oCssParser->parse()` –, use `getContents()`, then iterate over that collection and use instanceof to check whether you’re dealing with another `CSSList`, a `RuleSet`, a `Import` or a `Charset`.
|
||||
|
||||
To append a new item (selector, media query, etc.) to an existing `CSSList`, construct it using the constructor for this class and use the `append($oItem)` method.
|
||||
|
||||
#### RuleSet
|
||||
|
||||
`RuleSet` is a container for individual rules. The most common form of a rule set is one constrained by a selector. The following concrete subtypes exist:
|
||||
|
||||
* `AtRuleSet` – for generic at-rules which do not match the ones specifically mentioned like @import, @charset or @media. A common example for this is @font-face.
|
||||
* `DeclarationBlock` – a RuleSet constrained by a `Selector`; contains an array of selector objects (comma-separated in the CSS) as well as the rules to be applied to the matching elements.
|
||||
|
||||
Note: A `CSSList` can contain other `CSSList`s (and `Import`s as well as a `Charset`) while a `RuleSet` can only contain `Rule`s.
|
||||
|
||||
If you want to manipulate a `RuleSet`, use the methods `addRule(Rule $oRule)`, `getRules()` and `removeRule($mRule)` (which accepts either a Rule instance or a rule name; optionally suffixed by a dash to remove all related rules).
|
||||
|
||||
#### Rule
|
||||
|
||||
`Rule`s just have a key (the rule) and a value. These values are all instances of a `Value`.
|
||||
|
||||
#### Value
|
||||
|
||||
`Value` is an abstract class that only defines the `render` method. The concrete subclasses for atomic value types are:
|
||||
|
||||
* `Size` – consists of a numeric `size` value and a unit.
|
||||
* `Color` – colors can be input in the form #rrggbb, #rgb or schema(val1, val2, …) but are always stored as an array of ('s' => val1, 'c' => val2, 'h' => val3, …) and output in the second form.
|
||||
* `CSSString` – this is just a wrapper for quoted strings to distinguish them from keywords; always output with double quotes.
|
||||
* `URL` – URLs in CSS; always output in URL("") notation.
|
||||
|
||||
There is another abstract subclass of `Value`, `ValueList`. A `ValueList` represents a lists of `Value`s, separated by some separation character (mostly `,`, whitespace, or `/`). There are two types of `ValueList`s:
|
||||
|
||||
* `RuleValueList` – The default type, used to represent all multi-valued rules like `font: bold 12px/3 Helvetica, Verdana, sans-serif;` (where the value would be a whitespace-separated list of the primitive value `bold`, a slash-separated list and a comma-separated list).
|
||||
* `CSSFunction` – A special kind of value that also contains a function name and where the values are the function’s arguments. Also handles equals-sign-separated argument lists like `filter: alpha(opacity=90);`.
|
||||
|
||||
#### Convenience methods
|
||||
|
||||
There are a few convenience methods on Document to ease finding, manipulating and deleting rules:
|
||||
|
||||
* `getAllDeclarationBlocks()` – does what it says; no matter how deeply nested your selectors are. Aliased as `getAllSelectors()`.
|
||||
* `getAllRuleSets()` – does what it says; no matter how deeply nested your rule sets are.
|
||||
* `getAllValues()` – finds all `Value` objects inside `Rule`s.
|
||||
|
||||
## To-Do
|
||||
|
||||
* More convenience methods [like `selectorsWithElement($sId/Class/TagName)`, `attributesOfType($sType)`, `removeAttributesOfType($sType)`]
|
||||
* Real multibyte support. Currently only multibyte charsets whose first 255 code points take up only one byte and are identical with ASCII are supported (yes, UTF-8 fits this description).
|
||||
* Named color support (using `Color` instead of an anonymous string literal)
|
||||
|
||||
## Use cases
|
||||
|
||||
### Use `Parser` to prepend an id to all selectors
|
||||
|
||||
```php
|
||||
$sMyId = "#my_id";
|
||||
$oParser = new Sabberworm\CSS\Parser($sText);
|
||||
$oCss = $oParser->parse();
|
||||
foreach($oCss->getAllDeclarationBlocks() as $oBlock) {
|
||||
foreach($oBlock->getSelectors() as $oSelector) {
|
||||
//Loop over all selector parts (the comma-separated strings in a selector) and prepend the id
|
||||
$oSelector->setSelector($sMyId.' '.$oSelector->getSelector());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Shrink all absolute sizes to half
|
||||
|
||||
```php
|
||||
$oParser = new Sabberworm\CSS\Parser($sText);
|
||||
$oCss = $oParser->parse();
|
||||
foreach($oCss->getAllValues() as $mValue) {
|
||||
if($mValue instanceof CSSSize && !$mValue->isRelative()) {
|
||||
$mValue->setSize($mValue->getSize()/2);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Remove unwanted rules
|
||||
|
||||
```php
|
||||
$oParser = new Sabberworm\CSS\Parser($sText);
|
||||
$oCss = $oParser->parse();
|
||||
foreach($oCss->getAllRuleSets() as $oRuleSet) {
|
||||
$oRuleSet->removeRule('font-'); //Note that the added dash will make this remove all rules starting with font- (like font-size, font-weight, etc.) as well as a potential font-rule
|
||||
$oRuleSet->removeRule('cursor');
|
||||
}
|
||||
```
|
||||
|
||||
### Output
|
||||
|
||||
To output the entire CSS document into a variable, just use `->render()`:
|
||||
|
||||
```php
|
||||
$oCssParser = new Sabberworm\CSS\Parser(file_get_contents('somefile.css'));
|
||||
$oCssDocument = $oCssParser->parse();
|
||||
print $oCssDocument->render();
|
||||
```
|
||||
|
||||
If you want to format the output, pass an instance of type `Sabberworm\CSS\OutputFormat`:
|
||||
|
||||
```php
|
||||
$oFormat = Sabberworm\CSS\OutputFormat::create()->indentWithSpaces(4)->setSpaceBetweenRules("\n");
|
||||
print $oCssDocument->render($oFormat);
|
||||
```
|
||||
|
||||
Or use one of the predefined formats:
|
||||
|
||||
```php
|
||||
print $oCssDocument->render(Sabberworm\CSS\OutputFormat::createPretty());
|
||||
print $oCssDocument->render(Sabberworm\CSS\OutputFormat::createCompact());
|
||||
```
|
||||
|
||||
To see what you can do with output formatting, look at the tests in `tests/Sabberworm/CSS/OutputFormatTest.php`.
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1 (At-Rules)
|
||||
|
||||
#### Input
|
||||
|
||||
```css
|
||||
@charset "utf-8";
|
||||
|
||||
@font-face {
|
||||
font-family: "CrassRoots";
|
||||
src: url("../media/cr.ttf")
|
||||
}
|
||||
|
||||
html, body {
|
||||
font-size: 1.6em
|
||||
}
|
||||
|
||||
@keyframes mymove {
|
||||
from { top: 0px; }
|
||||
to { top: 200px; }
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### Structure (`var_dump()`)
|
||||
|
||||
```php
|
||||
class Sabberworm\CSS\CSSList\Document#4 (2) {
|
||||
protected $aContents =>
|
||||
array(4) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Property\Charset#6 (2) {
|
||||
private $sCharset =>
|
||||
class Sabberworm\CSS\Value\CSSString#5 (2) {
|
||||
private $sString =>
|
||||
string(5) "utf-8"
|
||||
protected $iLineNo =>
|
||||
int(1)
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(1)
|
||||
}
|
||||
[1] =>
|
||||
class Sabberworm\CSS\RuleSet\AtRuleSet#7 (4) {
|
||||
private $sType =>
|
||||
string(9) "font-face"
|
||||
private $sArgs =>
|
||||
string(0) ""
|
||||
private $aRules =>
|
||||
array(2) {
|
||||
'font-family' =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Rule\Rule#8 (4) {
|
||||
private $sRule =>
|
||||
string(11) "font-family"
|
||||
private $mValue =>
|
||||
class Sabberworm\CSS\Value\CSSString#9 (2) {
|
||||
private $sString =>
|
||||
string(10) "CrassRoots"
|
||||
protected $iLineNo =>
|
||||
int(4)
|
||||
}
|
||||
private $bIsImportant =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(4)
|
||||
}
|
||||
}
|
||||
'src' =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Rule\Rule#10 (4) {
|
||||
private $sRule =>
|
||||
string(3) "src"
|
||||
private $mValue =>
|
||||
class Sabberworm\CSS\Value\URL#11 (2) {
|
||||
private $oURL =>
|
||||
class Sabberworm\CSS\Value\CSSString#12 (2) {
|
||||
private $sString =>
|
||||
string(15) "../media/cr.ttf"
|
||||
protected $iLineNo =>
|
||||
int(5)
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(5)
|
||||
}
|
||||
private $bIsImportant =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(5)
|
||||
}
|
||||
}
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(3)
|
||||
}
|
||||
[2] =>
|
||||
class Sabberworm\CSS\RuleSet\DeclarationBlock#13 (3) {
|
||||
private $aSelectors =>
|
||||
array(2) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Property\Selector#14 (2) {
|
||||
private $sSelector =>
|
||||
string(4) "html"
|
||||
private $iSpecificity =>
|
||||
NULL
|
||||
}
|
||||
[1] =>
|
||||
class Sabberworm\CSS\Property\Selector#15 (2) {
|
||||
private $sSelector =>
|
||||
string(4) "body"
|
||||
private $iSpecificity =>
|
||||
NULL
|
||||
}
|
||||
}
|
||||
private $aRules =>
|
||||
array(1) {
|
||||
'font-size' =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Rule\Rule#16 (4) {
|
||||
private $sRule =>
|
||||
string(9) "font-size"
|
||||
private $mValue =>
|
||||
class Sabberworm\CSS\Value\Size#17 (4) {
|
||||
private $fSize =>
|
||||
double(1.6)
|
||||
private $sUnit =>
|
||||
string(2) "em"
|
||||
private $bIsColorComponent =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(9)
|
||||
}
|
||||
private $bIsImportant =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(9)
|
||||
}
|
||||
}
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(8)
|
||||
}
|
||||
[3] =>
|
||||
class Sabberworm\CSS\CSSList\KeyFrame#18 (4) {
|
||||
private $vendorKeyFrame =>
|
||||
string(9) "keyframes"
|
||||
private $animationName =>
|
||||
string(6) "mymove"
|
||||
protected $aContents =>
|
||||
array(2) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\RuleSet\DeclarationBlock#19 (3) {
|
||||
private $aSelectors =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Property\Selector#20 (2) {
|
||||
private $sSelector =>
|
||||
string(4) "from"
|
||||
private $iSpecificity =>
|
||||
NULL
|
||||
}
|
||||
}
|
||||
private $aRules =>
|
||||
array(1) {
|
||||
'top' =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Rule\Rule#21 (4) {
|
||||
private $sRule =>
|
||||
string(3) "top"
|
||||
private $mValue =>
|
||||
class Sabberworm\CSS\Value\Size#22 (4) {
|
||||
private $fSize =>
|
||||
double(0)
|
||||
private $sUnit =>
|
||||
string(2) "px"
|
||||
private $bIsColorComponent =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(13)
|
||||
}
|
||||
private $bIsImportant =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(13)
|
||||
}
|
||||
}
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(13)
|
||||
}
|
||||
[1] =>
|
||||
class Sabberworm\CSS\RuleSet\DeclarationBlock#23 (3) {
|
||||
private $aSelectors =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Property\Selector#24 (2) {
|
||||
private $sSelector =>
|
||||
string(2) "to"
|
||||
private $iSpecificity =>
|
||||
NULL
|
||||
}
|
||||
}
|
||||
private $aRules =>
|
||||
array(1) {
|
||||
'top' =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Rule\Rule#25 (4) {
|
||||
private $sRule =>
|
||||
string(3) "top"
|
||||
private $mValue =>
|
||||
class Sabberworm\CSS\Value\Size#26 (4) {
|
||||
private $fSize =>
|
||||
double(200)
|
||||
private $sUnit =>
|
||||
string(2) "px"
|
||||
private $bIsColorComponent =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(14)
|
||||
}
|
||||
private $bIsImportant =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(14)
|
||||
}
|
||||
}
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(14)
|
||||
}
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(12)
|
||||
}
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(1)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### Output (`render()`)
|
||||
|
||||
```css
|
||||
@charset "utf-8";
|
||||
@font-face {font-family: "CrassRoots";src: url("../media/cr.ttf");}
|
||||
html, body {font-size: 1.6em;}
|
||||
@keyframes mymove {from {top: 0px;}
|
||||
to {top: 200px;}}
|
||||
```
|
||||
|
||||
### Example 2 (Values)
|
||||
|
||||
#### Input
|
||||
|
||||
```css
|
||||
#header {
|
||||
margin: 10px 2em 1cm 2%;
|
||||
font-family: Verdana, Helvetica, "Gill Sans", sans-serif;
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### Structure (`var_dump()`)
|
||||
|
||||
```php
|
||||
class Sabberworm\CSS\CSSList\Document#4 (2) {
|
||||
protected $aContents =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\RuleSet\DeclarationBlock#5 (3) {
|
||||
private $aSelectors =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Property\Selector#6 (2) {
|
||||
private $sSelector =>
|
||||
string(7) "#header"
|
||||
private $iSpecificity =>
|
||||
NULL
|
||||
}
|
||||
}
|
||||
private $aRules =>
|
||||
array(3) {
|
||||
'margin' =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Rule\Rule#7 (4) {
|
||||
private $sRule =>
|
||||
string(6) "margin"
|
||||
private $mValue =>
|
||||
class Sabberworm\CSS\Value\RuleValueList#12 (3) {
|
||||
protected $aComponents =>
|
||||
array(4) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Value\Size#8 (4) {
|
||||
private $fSize =>
|
||||
double(10)
|
||||
private $sUnit =>
|
||||
string(2) "px"
|
||||
private $bIsColorComponent =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(2)
|
||||
}
|
||||
[1] =>
|
||||
class Sabberworm\CSS\Value\Size#9 (4) {
|
||||
private $fSize =>
|
||||
double(2)
|
||||
private $sUnit =>
|
||||
string(2) "em"
|
||||
private $bIsColorComponent =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(2)
|
||||
}
|
||||
[2] =>
|
||||
class Sabberworm\CSS\Value\Size#10 (4) {
|
||||
private $fSize =>
|
||||
double(1)
|
||||
private $sUnit =>
|
||||
string(2) "cm"
|
||||
private $bIsColorComponent =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(2)
|
||||
}
|
||||
[3] =>
|
||||
class Sabberworm\CSS\Value\Size#11 (4) {
|
||||
private $fSize =>
|
||||
double(2)
|
||||
private $sUnit =>
|
||||
string(1) "%"
|
||||
private $bIsColorComponent =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(2)
|
||||
}
|
||||
}
|
||||
protected $sSeparator =>
|
||||
string(1) " "
|
||||
protected $iLineNo =>
|
||||
int(2)
|
||||
}
|
||||
private $bIsImportant =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(2)
|
||||
}
|
||||
}
|
||||
'font-family' =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Rule\Rule#13 (4) {
|
||||
private $sRule =>
|
||||
string(11) "font-family"
|
||||
private $mValue =>
|
||||
class Sabberworm\CSS\Value\RuleValueList#15 (3) {
|
||||
protected $aComponents =>
|
||||
array(4) {
|
||||
[0] =>
|
||||
string(7) "Verdana"
|
||||
[1] =>
|
||||
string(9) "Helvetica"
|
||||
[2] =>
|
||||
class Sabberworm\CSS\Value\CSSString#14 (2) {
|
||||
private $sString =>
|
||||
string(9) "Gill Sans"
|
||||
protected $iLineNo =>
|
||||
int(3)
|
||||
}
|
||||
[3] =>
|
||||
string(10) "sans-serif"
|
||||
}
|
||||
protected $sSeparator =>
|
||||
string(1) ","
|
||||
protected $iLineNo =>
|
||||
int(3)
|
||||
}
|
||||
private $bIsImportant =>
|
||||
bool(false)
|
||||
protected $iLineNo =>
|
||||
int(3)
|
||||
}
|
||||
}
|
||||
'color' =>
|
||||
array(1) {
|
||||
[0] =>
|
||||
class Sabberworm\CSS\Rule\Rule#16 (4) {
|
||||
private $sRule =>
|
||||
string(5) "color"
|
||||
private $mValue =>
|
||||
string(3) "red"
|
||||
private $bIsImportant =>
|
||||
bool(true)
|
||||
protected $iLineNo =>
|
||||
int(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(1)
|
||||
}
|
||||
}
|
||||
protected $iLineNo =>
|
||||
int(1)
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
#### Output (`render()`)
|
||||
|
||||
```css
|
||||
#header {margin: 10px 2em 1cm 2%;font-family: Verdana,Helvetica,"Gill Sans",sans-serif;color: red !important;}
|
||||
```
|
||||
|
||||
## Contributors/Thanks to
|
||||
|
||||
* [raxbg](https://github.com/raxbg) for contributions to parse `calc`, grid lines, and various bugfixes.
|
||||
* [westonruter](https://github.com/westonruter) for bugfixes and improvements.
|
||||
* [FMCorz](https://github.com/FMCorz) for many patches and suggestions, for being able to parse comments and IE hacks (in lenient mode).
|
||||
* [Lullabot](https://github.com/Lullabot) for a patch that allows to know the line number for each parsed token.
|
||||
* [ju1ius](https://github.com/ju1ius) for the specificity parsing code and the ability to expand/compact shorthand properties.
|
||||
* [ossinkine](https://github.com/ossinkine) for a 150 time performance boost.
|
||||
* [GaryJones](https://github.com/GaryJones) for lots of input and [http://css-specificity.info/](http://css-specificity.info/).
|
||||
* [docteurklein](https://github.com/docteurklein) for output formatting and `CSSList->remove()` inspiration.
|
||||
* [nicolopignatelli](https://github.com/nicolopignatelli) for PSR-0 compatibility.
|
||||
* [diegoembarcadero](https://github.com/diegoembarcadero) for keyframe at-rule parsing.
|
||||
* [goetas](https://github.com/goetas) for @namespace at-rule support.
|
||||
* [View full list](https://github.com/sabberworm/PHP-CSS-Parser/contributors)
|
||||
|
||||
## Misc
|
||||
|
||||
* Legacy Support: The latest pre-PSR-0 version of this project can be checked with the `0.9.0` tag.
|
||||
* Running Tests: To run all unit tests for this project, run `composer install` to install phpunit and use `./vendor/phpunit/phpunit/phpunit`.
|
||||
|
||||
## License
|
||||
|
||||
PHP-CSS-Parser is freely distributable under the terms of an MIT-style license.
|
||||
|
||||
Copyright (c) 2011 Raphael Schweikert, http://sabberworm.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
21
vendor/sabberworm/php-css-parser/composer.json
vendored
Normal file
21
vendor/sabberworm/php-css-parser/composer.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "sabberworm/php-css-parser",
|
||||
"type": "library",
|
||||
"description": "Parser for CSS Files written in PHP",
|
||||
"keywords": ["parser", "css", "stylesheet"],
|
||||
"homepage": "http://www.sabberworm.com/blog/2010/6/10/php-css-parser",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{"name": "Raphael Schweikert"}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.8",
|
||||
"codacy/coverage": "^1.4"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Sabberworm\\CSS": "lib/" }
|
||||
}
|
||||
}
|
||||
1478
vendor/sabberworm/php-css-parser/composer.lock
generated
vendored
Normal file
1478
vendor/sabberworm/php-css-parser/composer.lock
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
50
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/AtRuleBlockList.php
vendored
Normal file
50
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/AtRuleBlockList.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\Property\AtRule;
|
||||
|
||||
/**
|
||||
* A BlockList constructed by an unknown @-rule. @media rules are rendered into AtRuleBlockList objects.
|
||||
*/
|
||||
class AtRuleBlockList extends CSSBlockList implements AtRule {
|
||||
|
||||
private $sType;
|
||||
private $sArgs;
|
||||
|
||||
public function __construct($sType, $sArgs = '', $iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
$this->sType = $sType;
|
||||
$this->sArgs = $sArgs;
|
||||
}
|
||||
|
||||
public function atRuleName() {
|
||||
return $this->sType;
|
||||
}
|
||||
|
||||
public function atRuleArgs() {
|
||||
return $this->sArgs;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$sArgs = $this->sArgs;
|
||||
if($sArgs) {
|
||||
$sArgs = ' ' . $sArgs;
|
||||
}
|
||||
$sResult = $oOutputFormat->sBeforeAtRuleBlock;
|
||||
$sResult .= "@{$this->sType}$sArgs{$oOutputFormat->spaceBeforeOpeningBrace()}{";
|
||||
$sResult .= parent::render($oOutputFormat);
|
||||
$sResult .= '}';
|
||||
$sResult .= $oOutputFormat->sAfterAtRuleBlock;
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
public function isRootList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
107
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/CSSBlockList.php
vendored
Normal file
107
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/CSSBlockList.php
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\RuleSet\DeclarationBlock;
|
||||
use Sabberworm\CSS\RuleSet\RuleSet;
|
||||
use Sabberworm\CSS\Property\Selector;
|
||||
use Sabberworm\CSS\Rule\Rule;
|
||||
use Sabberworm\CSS\Value\ValueList;
|
||||
use Sabberworm\CSS\Value\CSSFunction;
|
||||
|
||||
/**
|
||||
* A CSSBlockList is a CSSList whose DeclarationBlocks are guaranteed to contain valid declaration blocks or at-rules.
|
||||
* Most CSSLists conform to this category but some at-rules (such as @keyframes) do not.
|
||||
*/
|
||||
abstract class CSSBlockList extends CSSList {
|
||||
public function __construct($iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
}
|
||||
|
||||
protected function allDeclarationBlocks(&$aResult) {
|
||||
foreach ($this->aContents as $mContent) {
|
||||
if ($mContent instanceof DeclarationBlock) {
|
||||
$aResult[] = $mContent;
|
||||
} else if ($mContent instanceof CSSBlockList) {
|
||||
$mContent->allDeclarationBlocks($aResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function allRuleSets(&$aResult) {
|
||||
foreach ($this->aContents as $mContent) {
|
||||
if ($mContent instanceof RuleSet) {
|
||||
$aResult[] = $mContent;
|
||||
} else if ($mContent instanceof CSSBlockList) {
|
||||
$mContent->allRuleSets($aResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function allValues($oElement, &$aResult, $sSearchString = null, $bSearchInFunctionArguments = false) {
|
||||
if ($oElement instanceof CSSBlockList) {
|
||||
foreach ($oElement->getContents() as $oContent) {
|
||||
$this->allValues($oContent, $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
}
|
||||
} else if ($oElement instanceof RuleSet) {
|
||||
foreach ($oElement->getRules($sSearchString) as $oRule) {
|
||||
$this->allValues($oRule, $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
}
|
||||
} else if ($oElement instanceof Rule) {
|
||||
$this->allValues($oElement->getValue(), $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
} else if ($oElement instanceof ValueList) {
|
||||
if ($bSearchInFunctionArguments || !($oElement instanceof CSSFunction)) {
|
||||
foreach ($oElement->getListComponents() as $mComponent) {
|
||||
$this->allValues($mComponent, $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Non-List Value or CSSString (CSS identifier)
|
||||
$aResult[] = $oElement;
|
||||
}
|
||||
}
|
||||
|
||||
protected function allSelectors(&$aResult, $sSpecificitySearch = null) {
|
||||
$aDeclarationBlocks = array();
|
||||
$this->allDeclarationBlocks($aDeclarationBlocks);
|
||||
foreach ($aDeclarationBlocks as $oBlock) {
|
||||
foreach ($oBlock->getSelectors() as $oSelector) {
|
||||
if ($sSpecificitySearch === null) {
|
||||
$aResult[] = $oSelector;
|
||||
} else {
|
||||
$sComparator = '===';
|
||||
$aSpecificitySearch = explode(' ', $sSpecificitySearch);
|
||||
$iTargetSpecificity = $aSpecificitySearch[0];
|
||||
if(count($aSpecificitySearch) > 1) {
|
||||
$sComparator = $aSpecificitySearch[0];
|
||||
$iTargetSpecificity = $aSpecificitySearch[1];
|
||||
}
|
||||
$iTargetSpecificity = (int)$iTargetSpecificity;
|
||||
$iSelectorSpecificity = $oSelector->getSpecificity();
|
||||
$bMatches = false;
|
||||
switch($sComparator) {
|
||||
case '<=':
|
||||
$bMatches = $iSelectorSpecificity <= $iTargetSpecificity;
|
||||
break;
|
||||
case '<':
|
||||
$bMatches = $iSelectorSpecificity < $iTargetSpecificity;
|
||||
break;
|
||||
case '>=':
|
||||
$bMatches = $iSelectorSpecificity >= $iTargetSpecificity;
|
||||
break;
|
||||
case '>':
|
||||
$bMatches = $iSelectorSpecificity > $iTargetSpecificity;
|
||||
break;
|
||||
default:
|
||||
$bMatches = $iSelectorSpecificity === $iTargetSpecificity;
|
||||
break;
|
||||
}
|
||||
if ($bMatches) {
|
||||
$aResult[] = $oSelector;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
348
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/CSSList.php
vendored
Normal file
348
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/CSSList.php
vendored
Normal file
@@ -0,0 +1,348 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\Comment\Commentable;
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\SourceException;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
|
||||
use Sabberworm\CSS\Property\AtRule;
|
||||
use Sabberworm\CSS\Property\Charset;
|
||||
use Sabberworm\CSS\Property\CSSNamespace;
|
||||
use Sabberworm\CSS\Property\Import;
|
||||
use Sabberworm\CSS\Property\Selector;
|
||||
use Sabberworm\CSS\Renderable;
|
||||
use Sabberworm\CSS\RuleSet\AtRuleSet;
|
||||
use Sabberworm\CSS\RuleSet\DeclarationBlock;
|
||||
use Sabberworm\CSS\RuleSet\RuleSet;
|
||||
use Sabberworm\CSS\Value\CSSString;
|
||||
use Sabberworm\CSS\Value\URL;
|
||||
use Sabberworm\CSS\Value\Value;
|
||||
|
||||
/**
|
||||
* A CSSList is the most generic container available. Its contents include RuleSet as well as other CSSList objects.
|
||||
* Also, it may contain Import and Charset objects stemming from @-rules.
|
||||
*/
|
||||
abstract class CSSList implements Renderable, Commentable {
|
||||
|
||||
protected $aComments;
|
||||
protected $aContents;
|
||||
protected $iLineNo;
|
||||
|
||||
public function __construct($iLineNo = 0) {
|
||||
$this->aComments = array();
|
||||
$this->aContents = array();
|
||||
$this->iLineNo = $iLineNo;
|
||||
}
|
||||
|
||||
public static function parseList(ParserState $oParserState, CSSList $oList) {
|
||||
$bIsRoot = $oList instanceof Document;
|
||||
if(is_string($oParserState)) {
|
||||
$oParserState = new ParserState($oParserState);
|
||||
}
|
||||
$bLenientParsing = $oParserState->getSettings()->bLenientParsing;
|
||||
while(!$oParserState->isEnd()) {
|
||||
$comments = $oParserState->consumeWhiteSpace();
|
||||
$oListItem = null;
|
||||
if($bLenientParsing) {
|
||||
try {
|
||||
$oListItem = self::parseListItem($oParserState, $oList);
|
||||
} catch (UnexpectedTokenException $e) {
|
||||
$oListItem = false;
|
||||
}
|
||||
} else {
|
||||
$oListItem = self::parseListItem($oParserState, $oList);
|
||||
}
|
||||
if($oListItem === null) {
|
||||
// List parsing finished
|
||||
return;
|
||||
}
|
||||
if($oListItem) {
|
||||
$oListItem->setComments($comments);
|
||||
$oList->append($oListItem);
|
||||
}
|
||||
$oParserState->consumeWhiteSpace();
|
||||
}
|
||||
if(!$bIsRoot && !$bLenientParsing) {
|
||||
throw new SourceException("Unexpected end of document", $oParserState->currentLine());
|
||||
}
|
||||
}
|
||||
|
||||
private static function parseListItem(ParserState $oParserState, CSSList $oList) {
|
||||
$bIsRoot = $oList instanceof Document;
|
||||
if ($oParserState->comes('@')) {
|
||||
$oAtRule = self::parseAtRule($oParserState);
|
||||
if($oAtRule instanceof Charset) {
|
||||
if(!$bIsRoot) {
|
||||
throw new UnexpectedTokenException('@charset may only occur in root document', '', 'custom', $oParserState->currentLine());
|
||||
}
|
||||
if(count($oList->getContents()) > 0) {
|
||||
throw new UnexpectedTokenException('@charset must be the first parseable token in a document', '', 'custom', $oParserState->currentLine());
|
||||
}
|
||||
$oParserState->setCharset($oAtRule->getCharset()->getString());
|
||||
}
|
||||
return $oAtRule;
|
||||
} else if ($oParserState->comes('}')) {
|
||||
$oParserState->consume('}');
|
||||
if ($bIsRoot) {
|
||||
if ($oParserState->getSettings()->bLenientParsing) {
|
||||
while ($oParserState->comes('}')) $oParserState->consume('}');
|
||||
return DeclarationBlock::parse($oParserState);
|
||||
} else {
|
||||
throw new SourceException("Unopened {", $oParserState->currentLine());
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return DeclarationBlock::parse($oParserState);
|
||||
}
|
||||
}
|
||||
|
||||
private static function parseAtRule(ParserState $oParserState) {
|
||||
$oParserState->consume('@');
|
||||
$sIdentifier = $oParserState->parseIdentifier();
|
||||
$iIdentifierLineNum = $oParserState->currentLine();
|
||||
$oParserState->consumeWhiteSpace();
|
||||
if ($sIdentifier === 'import') {
|
||||
$oLocation = URL::parse($oParserState);
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$sMediaQuery = null;
|
||||
if (!$oParserState->comes(';')) {
|
||||
$sMediaQuery = $oParserState->consumeUntil(';');
|
||||
}
|
||||
$oParserState->consume(';');
|
||||
return new Import($oLocation, $sMediaQuery, $iIdentifierLineNum);
|
||||
} else if ($sIdentifier === 'charset') {
|
||||
$sCharset = CSSString::parse($oParserState);
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$oParserState->consume(';');
|
||||
return new Charset($sCharset, $iIdentifierLineNum);
|
||||
} else if (self::identifierIs($sIdentifier, 'keyframes')) {
|
||||
$oResult = new KeyFrame($iIdentifierLineNum);
|
||||
$oResult->setVendorKeyFrame($sIdentifier);
|
||||
$oResult->setAnimationName(trim($oParserState->consumeUntil('{', false, true)));
|
||||
CSSList::parseList($oParserState, $oResult);
|
||||
return $oResult;
|
||||
} else if ($sIdentifier === 'namespace') {
|
||||
$sPrefix = null;
|
||||
$mUrl = Value::parsePrimitiveValue($oParserState);
|
||||
if (!$oParserState->comes(';')) {
|
||||
$sPrefix = $mUrl;
|
||||
$mUrl = Value::parsePrimitiveValue($oParserState);
|
||||
}
|
||||
$oParserState->consume(';');
|
||||
if ($sPrefix !== null && !is_string($sPrefix)) {
|
||||
throw new UnexpectedTokenException('Wrong namespace prefix', $sPrefix, 'custom', $iIdentifierLineNum);
|
||||
}
|
||||
if (!($mUrl instanceof CSSString || $mUrl instanceof URL)) {
|
||||
throw new UnexpectedTokenException('Wrong namespace url of invalid type', $mUrl, 'custom', $iIdentifierLineNum);
|
||||
}
|
||||
return new CSSNamespace($mUrl, $sPrefix, $iIdentifierLineNum);
|
||||
} else {
|
||||
//Unknown other at rule (font-face or such)
|
||||
$sArgs = trim($oParserState->consumeUntil('{', false, true));
|
||||
if (substr_count($sArgs, "(") != substr_count($sArgs, ")")) {
|
||||
if($oParserState->getSettings()->bLenientParsing) {
|
||||
return NULL;
|
||||
} else {
|
||||
throw new SourceException("Unmatched brace count in media query", $oParserState->currentLine());
|
||||
}
|
||||
}
|
||||
$bUseRuleSet = true;
|
||||
foreach(explode('/', AtRule::BLOCK_RULES) as $sBlockRuleName) {
|
||||
if(self::identifierIs($sIdentifier, $sBlockRuleName)) {
|
||||
$bUseRuleSet = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($bUseRuleSet) {
|
||||
$oAtRule = new AtRuleSet($sIdentifier, $sArgs, $iIdentifierLineNum);
|
||||
RuleSet::parseRuleSet($oParserState, $oAtRule);
|
||||
} else {
|
||||
$oAtRule = new AtRuleBlockList($sIdentifier, $sArgs, $iIdentifierLineNum);
|
||||
CSSList::parseList($oParserState, $oAtRule);
|
||||
}
|
||||
return $oAtRule;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an identifier for a given value. Since identifiers are all keywords, they can be vendor-prefixed. We need to check for these versions too.
|
||||
*/
|
||||
private static function identifierIs($sIdentifier, $sMatch) {
|
||||
return (strcasecmp($sIdentifier, $sMatch) === 0)
|
||||
?: preg_match("/^(-\\w+-)?$sMatch$/i", $sIdentifier) === 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend item to list of contents.
|
||||
*
|
||||
* @param object $oItem Item.
|
||||
*/
|
||||
public function prepend($oItem) {
|
||||
array_unshift($this->aContents, $oItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append item to list of contents.
|
||||
*
|
||||
* @param object $oItem Item.
|
||||
*/
|
||||
public function append($oItem) {
|
||||
$this->aContents[] = $oItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splice the list of contents.
|
||||
*
|
||||
* @param int $iOffset Offset.
|
||||
* @param int $iLength Length. Optional.
|
||||
* @param RuleSet[] $mReplacement Replacement. Optional.
|
||||
*/
|
||||
public function splice($iOffset, $iLength = null, $mReplacement = null) {
|
||||
array_splice($this->aContents, $iOffset, $iLength, $mReplacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item from the CSS list.
|
||||
* @param RuleSet|Import|Charset|CSSList $oItemToRemove May be a RuleSet (most likely a DeclarationBlock), a Import, a Charset or another CSSList (most likely a MediaQuery)
|
||||
* @return bool Whether the item was removed.
|
||||
*/
|
||||
public function remove($oItemToRemove) {
|
||||
$iKey = array_search($oItemToRemove, $this->aContents, true);
|
||||
if ($iKey !== false) {
|
||||
unset($this->aContents[$iKey]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces an item from the CSS list.
|
||||
* @param RuleSet|Import|Charset|CSSList $oItemToRemove May be a RuleSet (most likely a DeclarationBlock), a Import, a Charset or another CSSList (most likely a MediaQuery)
|
||||
*/
|
||||
public function replace($oOldItem, $oNewItem) {
|
||||
$iKey = array_search($oOldItem, $this->aContents, true);
|
||||
if ($iKey !== false) {
|
||||
array_splice($this->aContents, $iKey, 1, $oNewItem);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the contents.
|
||||
* @param array $aContents Objects to set as content.
|
||||
*/
|
||||
public function setContents(array $aContents) {
|
||||
$this->aContents = array();
|
||||
foreach ($aContents as $content) {
|
||||
$this->append($content);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a declaration block from the CSS list if it matches all given selectors.
|
||||
* @param array|string $mSelector The selectors to match.
|
||||
* @param boolean $bRemoveAll Whether to stop at the first declaration block found or remove all blocks
|
||||
*/
|
||||
public function removeDeclarationBlockBySelector($mSelector, $bRemoveAll = false) {
|
||||
if ($mSelector instanceof DeclarationBlock) {
|
||||
$mSelector = $mSelector->getSelectors();
|
||||
}
|
||||
if (!is_array($mSelector)) {
|
||||
$mSelector = explode(',', $mSelector);
|
||||
}
|
||||
foreach ($mSelector as $iKey => &$mSel) {
|
||||
if (!($mSel instanceof Selector)) {
|
||||
$mSel = new Selector($mSel);
|
||||
}
|
||||
}
|
||||
foreach ($this->aContents as $iKey => $mItem) {
|
||||
if (!($mItem instanceof DeclarationBlock)) {
|
||||
continue;
|
||||
}
|
||||
if ($mItem->getSelectors() == $mSelector) {
|
||||
unset($this->aContents[$iKey]);
|
||||
if (!$bRemoveAll) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$sResult = '';
|
||||
$bIsFirst = true;
|
||||
$oNextLevel = $oOutputFormat;
|
||||
if(!$this->isRootList()) {
|
||||
$oNextLevel = $oOutputFormat->nextLevel();
|
||||
}
|
||||
foreach ($this->aContents as $oContent) {
|
||||
$sRendered = $oOutputFormat->safely(function() use ($oNextLevel, $oContent) {
|
||||
return $oContent->render($oNextLevel);
|
||||
});
|
||||
if($sRendered === null) {
|
||||
continue;
|
||||
}
|
||||
if($bIsFirst) {
|
||||
$bIsFirst = false;
|
||||
$sResult .= $oNextLevel->spaceBeforeBlocks();
|
||||
} else {
|
||||
$sResult .= $oNextLevel->spaceBetweenBlocks();
|
||||
}
|
||||
$sResult .= $sRendered;
|
||||
}
|
||||
|
||||
if(!$bIsFirst) {
|
||||
// Had some output
|
||||
$sResult .= $oOutputFormat->spaceAfterBlocks();
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the list can not be further outdented. Only important when rendering.
|
||||
*/
|
||||
public abstract function isRootList();
|
||||
|
||||
public function getContents() {
|
||||
return $this->aContents;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aComments Array of comments.
|
||||
*/
|
||||
public function addComments(array $aComments) {
|
||||
$this->aComments = array_merge($this->aComments, $aComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getComments() {
|
||||
return $this->aComments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aComments Array containing Comment objects.
|
||||
*/
|
||||
public function setComments(array $aComments) {
|
||||
$this->aComments = $aComments;
|
||||
}
|
||||
|
||||
}
|
||||
110
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/Document.php
vendored
Normal file
110
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/Document.php
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
|
||||
/**
|
||||
* The root CSSList of a parsed file. Contains all top-level css contents, mostly declaration blocks, but also any @-rules encountered.
|
||||
*/
|
||||
class Document extends CSSBlockList {
|
||||
/**
|
||||
* Document constructor.
|
||||
* @param int $iLineNo
|
||||
*/
|
||||
public function __construct($iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
}
|
||||
|
||||
public static function parse(ParserState $oParserState) {
|
||||
$oDocument = new Document($oParserState->currentLine());
|
||||
CSSList::parseList($oParserState, $oDocument);
|
||||
return $oDocument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all DeclarationBlock objects recursively.
|
||||
*/
|
||||
public function getAllDeclarationBlocks() {
|
||||
$aResult = array();
|
||||
$this->allDeclarationBlocks($aResult);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getAllDeclarationBlocks()
|
||||
*/
|
||||
public function getAllSelectors() {
|
||||
return $this->getAllDeclarationBlocks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all RuleSet objects found recursively in the tree.
|
||||
*/
|
||||
public function getAllRuleSets() {
|
||||
$aResult = array();
|
||||
$this->allRuleSets($aResult);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all Value objects found recursively in the tree.
|
||||
* @param (object|string) $mElement the CSSList or RuleSet to start the search from (defaults to the whole document). If a string is given, it is used as rule name filter (@see{RuleSet->getRules()}).
|
||||
* @param (bool) $bSearchInFunctionArguments whether to also return Value objects used as Function arguments.
|
||||
*/
|
||||
public function getAllValues($mElement = null, $bSearchInFunctionArguments = false) {
|
||||
$sSearchString = null;
|
||||
if ($mElement === null) {
|
||||
$mElement = $this;
|
||||
} else if (is_string($mElement)) {
|
||||
$sSearchString = $mElement;
|
||||
$mElement = $this;
|
||||
}
|
||||
$aResult = array();
|
||||
$this->allValues($mElement, $aResult, $sSearchString, $bSearchInFunctionArguments);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all Selector objects found recursively in the tree.
|
||||
* Note that this does not yield the full DeclarationBlock that the selector belongs to (and, currently, there is no way to get to that).
|
||||
* @param $sSpecificitySearch An optional filter by specificity. May contain a comparison operator and a number or just a number (defaults to "==").
|
||||
* @example getSelectorsBySpecificity('>= 100')
|
||||
*/
|
||||
public function getSelectorsBySpecificity($sSpecificitySearch = null) {
|
||||
$aResult = array();
|
||||
$this->allSelectors($aResult, $sSpecificitySearch);
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands all shorthand properties to their long value
|
||||
*/
|
||||
public function expandShorthands() {
|
||||
foreach ($this->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->expandShorthands();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create shorthands properties whenever possible
|
||||
*/
|
||||
public function createShorthands() {
|
||||
foreach ($this->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->createShorthands();
|
||||
}
|
||||
}
|
||||
|
||||
// Override render() to make format argument optional
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat = null) {
|
||||
if($oOutputFormat === null) {
|
||||
$oOutputFormat = new \Sabberworm\CSS\OutputFormat();
|
||||
}
|
||||
return parent::render($oOutputFormat);
|
||||
}
|
||||
|
||||
public function isRootList() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
56
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/KeyFrame.php
vendored
Normal file
56
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/CSSList/KeyFrame.php
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\Property\AtRule;
|
||||
|
||||
class KeyFrame extends CSSList implements AtRule {
|
||||
|
||||
private $vendorKeyFrame;
|
||||
private $animationName;
|
||||
|
||||
public function __construct($iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
$this->vendorKeyFrame = null;
|
||||
$this->animationName = null;
|
||||
}
|
||||
|
||||
public function setVendorKeyFrame($vendorKeyFrame) {
|
||||
$this->vendorKeyFrame = $vendorKeyFrame;
|
||||
}
|
||||
|
||||
public function getVendorKeyFrame() {
|
||||
return $this->vendorKeyFrame;
|
||||
}
|
||||
|
||||
public function setAnimationName($animationName) {
|
||||
$this->animationName = $animationName;
|
||||
}
|
||||
|
||||
public function getAnimationName() {
|
||||
return $this->animationName;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$sResult = "@{$this->vendorKeyFrame} {$this->animationName}{$oOutputFormat->spaceBeforeOpeningBrace()}{";
|
||||
$sResult .= parent::render($oOutputFormat);
|
||||
$sResult .= '}';
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
public function isRootList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function atRuleName() {
|
||||
return $this->vendorKeyFrame;
|
||||
}
|
||||
|
||||
public function atRuleArgs() {
|
||||
return $this->animationName;
|
||||
}
|
||||
}
|
||||
51
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Comment/Comment.php
vendored
Normal file
51
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Comment/Comment.php
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Comment;
|
||||
|
||||
use Sabberworm\CSS\Renderable;
|
||||
|
||||
class Comment implements Renderable {
|
||||
protected $iLineNo;
|
||||
protected $sComment;
|
||||
|
||||
public function __construct($sComment = '', $iLineNo = 0) {
|
||||
$this->sComment = $sComment;
|
||||
$this->iLineNo = $iLineNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getComment() {
|
||||
return $this->sComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function setComment($sComment) {
|
||||
$this->sComment = $sComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
return '/*' . $this->sComment . '*/';
|
||||
}
|
||||
|
||||
}
|
||||
23
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Comment/Commentable.php
vendored
Normal file
23
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Comment/Commentable.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Comment;
|
||||
|
||||
interface Commentable {
|
||||
|
||||
/**
|
||||
* @param array $aComments Array of comments.
|
||||
*/
|
||||
public function addComments(array $aComments);
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getComments();
|
||||
|
||||
/**
|
||||
* @param array $aComments Array containing Comment objects.
|
||||
*/
|
||||
public function setComments(array $aComments);
|
||||
|
||||
|
||||
}
|
||||
322
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/OutputFormat.php
vendored
Normal file
322
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/OutputFormat.php
vendored
Normal file
@@ -0,0 +1,322 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS;
|
||||
|
||||
use Sabberworm\CSS\Parsing\OutputException;
|
||||
|
||||
/**
|
||||
* Class OutputFormat
|
||||
*
|
||||
* @method OutputFormat setSemicolonAfterLastRule( bool $bSemicolonAfterLastRule ) Set whether semicolons are added after last rule.
|
||||
*/
|
||||
class OutputFormat {
|
||||
/**
|
||||
* Value format
|
||||
*/
|
||||
// " means double-quote, ' means single-quote
|
||||
public $sStringQuotingType = '"';
|
||||
// Output RGB colors in hash notation if possible
|
||||
public $bRGBHashNotation = true;
|
||||
|
||||
/**
|
||||
* Declaration format
|
||||
*/
|
||||
// Semicolon after the last rule of a declaration block can be omitted. To do that, set this false.
|
||||
public $bSemicolonAfterLastRule = true;
|
||||
|
||||
/**
|
||||
* Spacing
|
||||
* Note that these strings are not sanity-checked: the value should only consist of whitespace
|
||||
* Any newline character will be indented according to the current level.
|
||||
* The triples (After, Before, Between) can be set using a wildcard (e.g. `$oFormat->set('Space*Rules', "\n");`)
|
||||
*/
|
||||
public $sSpaceAfterRuleName = ' ';
|
||||
|
||||
public $sSpaceBeforeRules = '';
|
||||
public $sSpaceAfterRules = '';
|
||||
public $sSpaceBetweenRules = '';
|
||||
|
||||
public $sSpaceBeforeBlocks = '';
|
||||
public $sSpaceAfterBlocks = '';
|
||||
public $sSpaceBetweenBlocks = "\n";
|
||||
|
||||
// Content injected in and around @-rule blocks.
|
||||
public $sBeforeAtRuleBlock = '';
|
||||
public $sAfterAtRuleBlock = '';
|
||||
|
||||
// This is what’s printed before and after the comma if a declaration block contains multiple selectors.
|
||||
public $sSpaceBeforeSelectorSeparator = '';
|
||||
public $sSpaceAfterSelectorSeparator = ' ';
|
||||
// This is what’s printed after the comma of value lists
|
||||
public $sSpaceBeforeListArgumentSeparator = '';
|
||||
public $sSpaceAfterListArgumentSeparator = '';
|
||||
|
||||
public $sSpaceBeforeOpeningBrace = ' ';
|
||||
|
||||
// Content injected in and around declaration blocks.
|
||||
public $sBeforeDeclarationBlock = '';
|
||||
public $sAfterDeclarationBlockSelectors = '';
|
||||
public $sAfterDeclarationBlock = '';
|
||||
|
||||
/**
|
||||
* Indentation
|
||||
*/
|
||||
// Indentation character(s) per level. Only applicable if newlines are used in any of the spacing settings.
|
||||
public $sIndentation = "\t";
|
||||
|
||||
/**
|
||||
* Output exceptions.
|
||||
*/
|
||||
public $bIgnoreExceptions = false;
|
||||
|
||||
|
||||
private $oFormatter = null;
|
||||
private $oNextLevelFormat = null;
|
||||
private $iIndentationLevel = 0;
|
||||
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function get($sName) {
|
||||
$aVarPrefixes = array('a', 's', 'm', 'b', 'f', 'o', 'c', 'i');
|
||||
foreach($aVarPrefixes as $sPrefix) {
|
||||
$sFieldName = $sPrefix.ucfirst($sName);
|
||||
if(isset($this->$sFieldName)) {
|
||||
return $this->$sFieldName;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function set($aNames, $mValue) {
|
||||
$aVarPrefixes = array('a', 's', 'm', 'b', 'f', 'o', 'c', 'i');
|
||||
if(is_string($aNames) && strpos($aNames, '*') !== false) {
|
||||
$aNames = array(str_replace('*', 'Before', $aNames), str_replace('*', 'Between', $aNames), str_replace('*', 'After', $aNames));
|
||||
} else if(!is_array($aNames)) {
|
||||
$aNames = array($aNames);
|
||||
}
|
||||
foreach($aVarPrefixes as $sPrefix) {
|
||||
$bDidReplace = false;
|
||||
foreach($aNames as $sName) {
|
||||
$sFieldName = $sPrefix.ucfirst($sName);
|
||||
if(isset($this->$sFieldName)) {
|
||||
$this->$sFieldName = $mValue;
|
||||
$bDidReplace = true;
|
||||
}
|
||||
}
|
||||
if($bDidReplace) {
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
// Break the chain so the user knows this option is invalid
|
||||
return false;
|
||||
}
|
||||
|
||||
public function __call($sMethodName, $aArguments) {
|
||||
if(strpos($sMethodName, 'set') === 0) {
|
||||
return $this->set(substr($sMethodName, 3), $aArguments[0]);
|
||||
} else if(strpos($sMethodName, 'get') === 0) {
|
||||
return $this->get(substr($sMethodName, 3));
|
||||
} else if(method_exists('\\Sabberworm\\CSS\\OutputFormatter', $sMethodName)) {
|
||||
return call_user_func_array(array($this->getFormatter(), $sMethodName), $aArguments);
|
||||
} else {
|
||||
throw new \Exception('Unknown OutputFormat method called: '.$sMethodName);
|
||||
}
|
||||
}
|
||||
|
||||
public function indentWithTabs($iNumber = 1) {
|
||||
return $this->setIndentation(str_repeat("\t", $iNumber));
|
||||
}
|
||||
|
||||
public function indentWithSpaces($iNumber = 2) {
|
||||
return $this->setIndentation(str_repeat(" ", $iNumber));
|
||||
}
|
||||
|
||||
public function nextLevel() {
|
||||
if($this->oNextLevelFormat === null) {
|
||||
$this->oNextLevelFormat = clone $this;
|
||||
$this->oNextLevelFormat->iIndentationLevel++;
|
||||
$this->oNextLevelFormat->oFormatter = null;
|
||||
}
|
||||
return $this->oNextLevelFormat;
|
||||
}
|
||||
|
||||
public function beLenient() {
|
||||
$this->bIgnoreExceptions = true;
|
||||
}
|
||||
|
||||
public function getFormatter() {
|
||||
if($this->oFormatter === null) {
|
||||
$this->oFormatter = new OutputFormatter($this);
|
||||
}
|
||||
return $this->oFormatter;
|
||||
}
|
||||
|
||||
public function level() {
|
||||
return $this->iIndentationLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create format.
|
||||
*
|
||||
* @return OutputFormat Format.
|
||||
*/
|
||||
public static function create() {
|
||||
return new OutputFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create compact format.
|
||||
*
|
||||
* @return OutputFormat Format.
|
||||
*/
|
||||
public static function createCompact() {
|
||||
$format = self::create();
|
||||
$format->set('Space*Rules', "")->set('Space*Blocks', "")->setSpaceAfterRuleName('')->setSpaceBeforeOpeningBrace('')->setSpaceAfterSelectorSeparator('');
|
||||
return $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create pretty format.
|
||||
*
|
||||
* @return OutputFormat Format.
|
||||
*/
|
||||
public static function createPretty() {
|
||||
$format = self::create();
|
||||
$format->set('Space*Rules', "\n")->set('Space*Blocks', "\n")->setSpaceBetweenBlocks("\n\n")->set('SpaceAfterListArgumentSeparator', array('default' => '', ',' => ' '));
|
||||
return $format;
|
||||
}
|
||||
}
|
||||
|
||||
class OutputFormatter {
|
||||
private $oFormat;
|
||||
|
||||
public function __construct(OutputFormat $oFormat) {
|
||||
$this->oFormat = $oFormat;
|
||||
}
|
||||
|
||||
public function space($sName, $sType = null) {
|
||||
$sSpaceString = $this->oFormat->get("Space$sName");
|
||||
// If $sSpaceString is an array, we have multple values configured depending on the type of object the space applies to
|
||||
if(is_array($sSpaceString)) {
|
||||
if($sType !== null && isset($sSpaceString[$sType])) {
|
||||
$sSpaceString = $sSpaceString[$sType];
|
||||
} else {
|
||||
$sSpaceString = reset($sSpaceString);
|
||||
}
|
||||
}
|
||||
return $this->prepareSpace($sSpaceString);
|
||||
}
|
||||
|
||||
public function spaceAfterRuleName() {
|
||||
return $this->space('AfterRuleName');
|
||||
}
|
||||
|
||||
public function spaceBeforeRules() {
|
||||
return $this->space('BeforeRules');
|
||||
}
|
||||
|
||||
public function spaceAfterRules() {
|
||||
return $this->space('AfterRules');
|
||||
}
|
||||
|
||||
public function spaceBetweenRules() {
|
||||
return $this->space('BetweenRules');
|
||||
}
|
||||
|
||||
public function spaceBeforeBlocks() {
|
||||
return $this->space('BeforeBlocks');
|
||||
}
|
||||
|
||||
public function spaceAfterBlocks() {
|
||||
return $this->space('AfterBlocks');
|
||||
}
|
||||
|
||||
public function spaceBetweenBlocks() {
|
||||
return $this->space('BetweenBlocks');
|
||||
}
|
||||
|
||||
public function spaceBeforeSelectorSeparator() {
|
||||
return $this->space('BeforeSelectorSeparator');
|
||||
}
|
||||
|
||||
public function spaceAfterSelectorSeparator() {
|
||||
return $this->space('AfterSelectorSeparator');
|
||||
}
|
||||
|
||||
public function spaceBeforeListArgumentSeparator($sSeparator) {
|
||||
return $this->space('BeforeListArgumentSeparator', $sSeparator);
|
||||
}
|
||||
|
||||
public function spaceAfterListArgumentSeparator($sSeparator) {
|
||||
return $this->space('AfterListArgumentSeparator', $sSeparator);
|
||||
}
|
||||
|
||||
public function spaceBeforeOpeningBrace() {
|
||||
return $this->space('BeforeOpeningBrace');
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the given code, either swallowing or passing exceptions, depending on the bIgnoreExceptions setting.
|
||||
*/
|
||||
public function safely($cCode) {
|
||||
if($this->oFormat->get('IgnoreExceptions')) {
|
||||
// If output exceptions are ignored, run the code with exception guards
|
||||
try {
|
||||
return $cCode();
|
||||
} catch (OutputException $e) {
|
||||
return null;
|
||||
} //Do nothing
|
||||
} else {
|
||||
// Run the code as-is
|
||||
return $cCode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone of the implode function but calls ->render with the current output format instead of __toString()
|
||||
*/
|
||||
public function implode($sSeparator, $aValues, $bIncreaseLevel = false) {
|
||||
$sResult = '';
|
||||
$oFormat = $this->oFormat;
|
||||
if($bIncreaseLevel) {
|
||||
$oFormat = $oFormat->nextLevel();
|
||||
}
|
||||
$bIsFirst = true;
|
||||
foreach($aValues as $mValue) {
|
||||
if($bIsFirst) {
|
||||
$bIsFirst = false;
|
||||
} else {
|
||||
$sResult .= $sSeparator;
|
||||
}
|
||||
if($mValue instanceof \Sabberworm\CSS\Renderable) {
|
||||
$sResult .= $mValue->render($oFormat);
|
||||
} else {
|
||||
$sResult .= $mValue;
|
||||
}
|
||||
}
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
public function removeLastSemicolon($sString) {
|
||||
if($this->oFormat->get('SemicolonAfterLastRule')) {
|
||||
return $sString;
|
||||
}
|
||||
$sString = explode(';', $sString);
|
||||
if(count($sString) < 2) {
|
||||
return $sString[0];
|
||||
}
|
||||
$sLast = array_pop($sString);
|
||||
$sNextToLast = array_pop($sString);
|
||||
array_push($sString, $sNextToLast.$sLast);
|
||||
return implode(';', $sString);
|
||||
}
|
||||
|
||||
private function prepareSpace($sSpaceString) {
|
||||
return str_replace("\n", "\n".$this->indent(), $sSpaceString);
|
||||
}
|
||||
|
||||
private function indent() {
|
||||
return str_repeat($this->oFormat->sIndentation, $this->oFormat->level());
|
||||
}
|
||||
}
|
||||
41
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parser.php
vendored
Normal file
41
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parser.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS;
|
||||
|
||||
use Sabberworm\CSS\CSSList\Document;
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
|
||||
/**
|
||||
* Parser class parses CSS from text into a data structure.
|
||||
*/
|
||||
class Parser {
|
||||
private $oParserState;
|
||||
|
||||
/**
|
||||
* Parser constructor.
|
||||
* Note that that iLineNo starts from 1 and not 0
|
||||
*
|
||||
* @param $sText
|
||||
* @param Settings|null $oParserSettings
|
||||
* @param int $iLineNo
|
||||
*/
|
||||
public function __construct($sText, Settings $oParserSettings = null, $iLineNo = 1) {
|
||||
if ($oParserSettings === null) {
|
||||
$oParserSettings = Settings::create();
|
||||
}
|
||||
$this->oParserState = new ParserState($sText, $oParserSettings, $iLineNo);
|
||||
}
|
||||
|
||||
public function setCharset($sCharset) {
|
||||
$this->oParserState->setCharset($sCharset);
|
||||
}
|
||||
|
||||
public function getCharset() {
|
||||
$this->oParserState->getCharset();
|
||||
}
|
||||
|
||||
public function parse() {
|
||||
return Document::parse($this->oParserState);
|
||||
}
|
||||
|
||||
}
|
||||
12
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parsing/OutputException.php
vendored
Normal file
12
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parsing/OutputException.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Parsing;
|
||||
|
||||
/**
|
||||
* Thrown if the CSS parsers attempts to print something invalid
|
||||
*/
|
||||
class OutputException extends SourceException {
|
||||
public function __construct($sMessage, $iLineNo = 0) {
|
||||
parent::__construct($sMessage, $iLineNo);
|
||||
}
|
||||
}
|
||||
310
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parsing/ParserState.php
vendored
Normal file
310
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parsing/ParserState.php
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
<?php
|
||||
namespace Sabberworm\CSS\Parsing;
|
||||
|
||||
use Sabberworm\CSS\Comment\Comment;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
|
||||
use Sabberworm\CSS\Settings;
|
||||
|
||||
class ParserState {
|
||||
private $oParserSettings;
|
||||
|
||||
private $sText;
|
||||
|
||||
private $aText;
|
||||
private $iCurrentPosition;
|
||||
private $sCharset;
|
||||
private $iLength;
|
||||
private $iLineNo;
|
||||
|
||||
public function __construct($sText, Settings $oParserSettings, $iLineNo = 1) {
|
||||
$this->oParserSettings = $oParserSettings;
|
||||
$this->sText = $sText;
|
||||
$this->iCurrentPosition = 0;
|
||||
$this->iLineNo = $iLineNo;
|
||||
$this->setCharset($this->oParserSettings->sDefaultCharset);
|
||||
}
|
||||
|
||||
public function setCharset($sCharset) {
|
||||
$this->sCharset = $sCharset;
|
||||
$this->aText = $this->strsplit($this->sText);
|
||||
$this->iLength = count($this->aText);
|
||||
}
|
||||
|
||||
public function getCharset() {
|
||||
$this->oParserHelper->getCharset();
|
||||
return $this->sCharset;
|
||||
}
|
||||
|
||||
public function currentLine() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
public function getSettings() {
|
||||
return $this->oParserSettings;
|
||||
}
|
||||
|
||||
public function parseIdentifier($bIgnoreCase = true) {
|
||||
$sResult = $this->parseCharacter(true);
|
||||
if ($sResult === null) {
|
||||
throw new UnexpectedTokenException($sResult, $this->peek(5), 'identifier', $this->iLineNo);
|
||||
}
|
||||
$sCharacter = null;
|
||||
while (($sCharacter = $this->parseCharacter(true)) !== null) {
|
||||
$sResult .= $sCharacter;
|
||||
}
|
||||
if ($bIgnoreCase) {
|
||||
$sResult = $this->strtolower($sResult);
|
||||
}
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
public function parseCharacter($bIsForIdentifier) {
|
||||
if ($this->peek() === '\\') {
|
||||
if ($bIsForIdentifier && $this->oParserSettings->bLenientParsing && ($this->comes('\0') || $this->comes('\9'))) {
|
||||
// Non-strings can contain \0 or \9 which is an IE hack supported in lenient parsing.
|
||||
return null;
|
||||
}
|
||||
$this->consume('\\');
|
||||
if ($this->comes('\n') || $this->comes('\r')) {
|
||||
return '';
|
||||
}
|
||||
if (preg_match('/[0-9a-fA-F]/Su', $this->peek()) === 0) {
|
||||
return $this->consume(1);
|
||||
}
|
||||
$sUnicode = $this->consumeExpression('/^[0-9a-fA-F]{1,6}/u', 6);
|
||||
if ($this->strlen($sUnicode) < 6) {
|
||||
//Consume whitespace after incomplete unicode escape
|
||||
if (preg_match('/\\s/isSu', $this->peek())) {
|
||||
if ($this->comes('\r\n')) {
|
||||
$this->consume(2);
|
||||
} else {
|
||||
$this->consume(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
$iUnicode = intval($sUnicode, 16);
|
||||
$sUtf32 = "";
|
||||
for ($i = 0; $i < 4; ++$i) {
|
||||
$sUtf32 .= chr($iUnicode & 0xff);
|
||||
$iUnicode = $iUnicode >> 8;
|
||||
}
|
||||
return iconv('utf-32le', $this->sCharset, $sUtf32);
|
||||
}
|
||||
if ($bIsForIdentifier) {
|
||||
$peek = ord($this->peek());
|
||||
// Ranges: a-z A-Z 0-9 - _
|
||||
if (($peek >= 97 && $peek <= 122) ||
|
||||
($peek >= 65 && $peek <= 90) ||
|
||||
($peek >= 48 && $peek <= 57) ||
|
||||
($peek === 45) ||
|
||||
($peek === 95) ||
|
||||
($peek > 0xa1)) {
|
||||
return $this->consume(1);
|
||||
}
|
||||
} else {
|
||||
return $this->consume(1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function consumeWhiteSpace() {
|
||||
$comments = array();
|
||||
do {
|
||||
while (preg_match('/\\s/isSu', $this->peek()) === 1) {
|
||||
$this->consume(1);
|
||||
}
|
||||
if($this->oParserSettings->bLenientParsing) {
|
||||
try {
|
||||
$oComment = $this->consumeComment();
|
||||
} catch(UnexpectedTokenException $e) {
|
||||
// When we can’t find the end of a comment, we assume the document is finished.
|
||||
$this->iCurrentPosition = $this->iLength;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$oComment = $this->consumeComment();
|
||||
}
|
||||
if ($oComment !== false) {
|
||||
$comments[] = $oComment;
|
||||
}
|
||||
} while($oComment !== false);
|
||||
return $comments;
|
||||
}
|
||||
|
||||
public function comes($sString, $bCaseInsensitive = false) {
|
||||
$sPeek = $this->peek(strlen($sString));
|
||||
return ($sPeek == '')
|
||||
? false
|
||||
: $this->streql($sPeek, $sString, $bCaseInsensitive);
|
||||
}
|
||||
|
||||
public function peek($iLength = 1, $iOffset = 0) {
|
||||
$iOffset += $this->iCurrentPosition;
|
||||
if ($iOffset >= $this->iLength) {
|
||||
return '';
|
||||
}
|
||||
return $this->substr($iOffset, $iLength);
|
||||
}
|
||||
|
||||
public function consume($mValue = 1) {
|
||||
if (is_string($mValue)) {
|
||||
$iLineCount = substr_count($mValue, "\n");
|
||||
$iLength = $this->strlen($mValue);
|
||||
if (!$this->streql($this->substr($this->iCurrentPosition, $iLength), $mValue)) {
|
||||
throw new UnexpectedTokenException($mValue, $this->peek(max($iLength, 5)), $this->iLineNo);
|
||||
}
|
||||
$this->iLineNo += $iLineCount;
|
||||
$this->iCurrentPosition += $this->strlen($mValue);
|
||||
return $mValue;
|
||||
} else {
|
||||
if ($this->iCurrentPosition + $mValue > $this->iLength) {
|
||||
throw new UnexpectedTokenException($mValue, $this->peek(5), 'count', $this->iLineNo);
|
||||
}
|
||||
$sResult = $this->substr($this->iCurrentPosition, $mValue);
|
||||
$iLineCount = substr_count($sResult, "\n");
|
||||
$this->iLineNo += $iLineCount;
|
||||
$this->iCurrentPosition += $mValue;
|
||||
return $sResult;
|
||||
}
|
||||
}
|
||||
|
||||
public function consumeExpression($mExpression, $iMaxLength = null) {
|
||||
$aMatches = null;
|
||||
$sInput = $iMaxLength !== null ? $this->peek($iMaxLength) : $this->inputLeft();
|
||||
if (preg_match($mExpression, $sInput, $aMatches, PREG_OFFSET_CAPTURE) === 1) {
|
||||
return $this->consume($aMatches[0][0]);
|
||||
}
|
||||
throw new UnexpectedTokenException($mExpression, $this->peek(5), 'expression', $this->iLineNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false|Comment
|
||||
*/
|
||||
public function consumeComment() {
|
||||
$mComment = false;
|
||||
if ($this->comes('/*')) {
|
||||
$iLineNo = $this->iLineNo;
|
||||
$this->consume(1);
|
||||
$mComment = '';
|
||||
while (($char = $this->consume(1)) !== '') {
|
||||
$mComment .= $char;
|
||||
if ($this->comes('*/')) {
|
||||
$this->consume(2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($mComment !== false) {
|
||||
// We skip the * which was included in the comment.
|
||||
return new Comment(substr($mComment, 1), $iLineNo);
|
||||
}
|
||||
|
||||
return $mComment;
|
||||
}
|
||||
|
||||
public function isEnd() {
|
||||
return $this->iCurrentPosition >= $this->iLength;
|
||||
}
|
||||
|
||||
public function consumeUntil($aEnd, $bIncludeEnd = false, $consumeEnd = false, array &$comments = array()) {
|
||||
$aEnd = is_array($aEnd) ? $aEnd : array($aEnd);
|
||||
$out = '';
|
||||
$start = $this->iCurrentPosition;
|
||||
|
||||
while (($char = $this->consume(1)) !== '') {
|
||||
if (in_array($char, $aEnd)) {
|
||||
if ($bIncludeEnd) {
|
||||
$out .= $char;
|
||||
} elseif (!$consumeEnd) {
|
||||
$this->iCurrentPosition -= $this->strlen($char);
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
$out .= $char;
|
||||
if ($comment = $this->consumeComment()) {
|
||||
$comments[] = $comment;
|
||||
}
|
||||
}
|
||||
|
||||
$this->iCurrentPosition = $start;
|
||||
throw new UnexpectedTokenException('One of ("'.implode('","', $aEnd).'")', $this->peek(5), 'search', $this->iLineNo);
|
||||
}
|
||||
|
||||
private function inputLeft() {
|
||||
return $this->substr($this->iCurrentPosition, -1);
|
||||
}
|
||||
|
||||
public function streql($sString1, $sString2, $bCaseInsensitive = true) {
|
||||
if($bCaseInsensitive) {
|
||||
return $this->strtolower($sString1) === $this->strtolower($sString2);
|
||||
} else {
|
||||
return $sString1 === $sString2;
|
||||
}
|
||||
}
|
||||
|
||||
public function backtrack($iAmount) {
|
||||
$this->iCurrentPosition -= $iAmount;
|
||||
}
|
||||
|
||||
public function strlen($sString) {
|
||||
if ($this->oParserSettings->bMultibyteSupport) {
|
||||
return mb_strlen($sString, $this->sCharset);
|
||||
} else {
|
||||
return strlen($sString);
|
||||
}
|
||||
}
|
||||
|
||||
private function substr($iStart, $iLength) {
|
||||
if ($iLength < 0) {
|
||||
$iLength = $this->iLength - $iStart + $iLength;
|
||||
}
|
||||
if ($iStart + $iLength > $this->iLength) {
|
||||
$iLength = $this->iLength - $iStart;
|
||||
}
|
||||
$sResult = '';
|
||||
while ($iLength > 0) {
|
||||
$sResult .= $this->aText[$iStart];
|
||||
$iStart++;
|
||||
$iLength--;
|
||||
}
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
private function strtolower($sString) {
|
||||
if ($this->oParserSettings->bMultibyteSupport) {
|
||||
return mb_strtolower($sString, $this->sCharset);
|
||||
} else {
|
||||
return strtolower($sString);
|
||||
}
|
||||
}
|
||||
|
||||
private function strsplit($sString) {
|
||||
if ($this->oParserSettings->bMultibyteSupport) {
|
||||
if ($this->streql($this->sCharset, 'utf-8')) {
|
||||
return preg_split('//u', $sString, null, PREG_SPLIT_NO_EMPTY);
|
||||
} else {
|
||||
$iLength = mb_strlen($sString, $this->sCharset);
|
||||
$aResult = array();
|
||||
for ($i = 0; $i < $iLength; ++$i) {
|
||||
$aResult[] = mb_substr($sString, $i, 1, $this->sCharset);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
} else {
|
||||
if($sString === '') {
|
||||
return array();
|
||||
} else {
|
||||
return str_split($sString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function strpos($sString, $sNeedle, $iOffset) {
|
||||
if ($this->oParserSettings->bMultibyteSupport) {
|
||||
return mb_strpos($sString, $sNeedle, $iOffset, $this->sCharset);
|
||||
} else {
|
||||
return strpos($sString, $sNeedle, $iOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
18
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parsing/SourceException.php
vendored
Normal file
18
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parsing/SourceException.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Parsing;
|
||||
|
||||
class SourceException extends \Exception {
|
||||
private $iLineNo;
|
||||
public function __construct($sMessage, $iLineNo = 0) {
|
||||
$this->iLineNo = $iLineNo;
|
||||
if (!empty($iLineNo)) {
|
||||
$sMessage .= " [line no: $iLineNo]";
|
||||
}
|
||||
parent::__construct($sMessage);
|
||||
}
|
||||
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
}
|
||||
31
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parsing/UnexpectedTokenException.php
vendored
Normal file
31
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Parsing/UnexpectedTokenException.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Parsing;
|
||||
|
||||
/**
|
||||
* Thrown if the CSS parsers encounters a token it did not expect
|
||||
*/
|
||||
class UnexpectedTokenException extends SourceException {
|
||||
private $sExpected;
|
||||
private $sFound;
|
||||
// Possible values: literal, identifier, count, expression, search
|
||||
private $sMatchType;
|
||||
|
||||
public function __construct($sExpected, $sFound, $sMatchType = 'literal', $iLineNo = 0) {
|
||||
$this->sExpected = $sExpected;
|
||||
$this->sFound = $sFound;
|
||||
$this->sMatchType = $sMatchType;
|
||||
$sMessage = "Token “{$sExpected}” ({$sMatchType}) not found. Got “{$sFound}”.";
|
||||
if($this->sMatchType === 'search') {
|
||||
$sMessage = "Search for “{$sExpected}” returned no results. Context: “{$sFound}”.";
|
||||
} else if($this->sMatchType === 'count') {
|
||||
$sMessage = "Next token was expected to have {$sExpected} chars. Context: “{$sFound}”.";
|
||||
} else if($this->sMatchType === 'identifier') {
|
||||
$sMessage = "Identifier expected. Got “{$sFound}”";
|
||||
} else if($this->sMatchType === 'custom') {
|
||||
$sMessage = trim("$sExpected $sFound");
|
||||
}
|
||||
|
||||
parent::__construct($sMessage, $iLineNo);
|
||||
}
|
||||
}
|
||||
16
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/AtRule.php
vendored
Normal file
16
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/AtRule.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Property;
|
||||
|
||||
use Sabberworm\CSS\Renderable;
|
||||
use Sabberworm\CSS\Comment\Commentable;
|
||||
|
||||
interface AtRule extends Renderable, Commentable {
|
||||
// Since there are more set rules than block rules, we’re whitelisting the block rules and have anything else be treated as a set rule.
|
||||
const BLOCK_RULES = 'media/document/supports/region-style/font-feature-values';
|
||||
// …and more font-specific ones (to be used inside font-feature-values)
|
||||
const SET_RULES = 'font-face/counter-style/page/swash/styleset/annotation';
|
||||
|
||||
public function atRuleName();
|
||||
public function atRuleArgs();
|
||||
}
|
||||
75
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/CSSNamespace.php
vendored
Normal file
75
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/CSSNamespace.php
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Property;
|
||||
|
||||
/**
|
||||
* CSSNamespace represents an @namespace rule.
|
||||
*/
|
||||
class CSSNamespace implements AtRule {
|
||||
private $mUrl;
|
||||
private $sPrefix;
|
||||
private $iLineNo;
|
||||
protected $aComments;
|
||||
|
||||
public function __construct($mUrl, $sPrefix = null, $iLineNo = 0) {
|
||||
$this->mUrl = $mUrl;
|
||||
$this->sPrefix = $sPrefix;
|
||||
$this->iLineNo = $iLineNo;
|
||||
$this->aComments = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
return '@namespace '.($this->sPrefix === null ? '' : $this->sPrefix.' ').$this->mUrl->render($oOutputFormat).';';
|
||||
}
|
||||
|
||||
public function getUrl() {
|
||||
return $this->mUrl;
|
||||
}
|
||||
|
||||
public function getPrefix() {
|
||||
return $this->sPrefix;
|
||||
}
|
||||
|
||||
public function setUrl($mUrl) {
|
||||
$this->mUrl = $mUrl;
|
||||
}
|
||||
|
||||
public function setPrefix($sPrefix) {
|
||||
$this->sPrefix = $sPrefix;
|
||||
}
|
||||
|
||||
public function atRuleName() {
|
||||
return 'namespace';
|
||||
}
|
||||
|
||||
public function atRuleArgs() {
|
||||
$aResult = array($this->mUrl);
|
||||
if($this->sPrefix) {
|
||||
array_unshift($aResult, $this->sPrefix);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function addComments(array $aComments) {
|
||||
$this->aComments = array_merge($this->aComments, $aComments);
|
||||
}
|
||||
|
||||
public function getComments() {
|
||||
return $this->aComments;
|
||||
}
|
||||
|
||||
public function setComments(array $aComments) {
|
||||
$this->aComments = $aComments;
|
||||
}
|
||||
}
|
||||
66
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/Charset.php
vendored
Normal file
66
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/Charset.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Property;
|
||||
|
||||
/**
|
||||
* Class representing an @charset rule.
|
||||
* The following restrictions apply:
|
||||
* • May not be found in any CSSList other than the Document.
|
||||
* • May only appear at the very top of a Document’s contents.
|
||||
* • Must not appear more than once.
|
||||
*/
|
||||
class Charset implements AtRule {
|
||||
|
||||
private $sCharset;
|
||||
protected $iLineNo;
|
||||
protected $aComment;
|
||||
|
||||
public function __construct($sCharset, $iLineNo = 0) {
|
||||
$this->sCharset = $sCharset;
|
||||
$this->iLineNo = $iLineNo;
|
||||
$this->aComments = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
public function setCharset($sCharset) {
|
||||
$this->sCharset = $sCharset;
|
||||
}
|
||||
|
||||
public function getCharset() {
|
||||
return $this->sCharset;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
return "@charset {$this->sCharset->render($oOutputFormat)};";
|
||||
}
|
||||
|
||||
public function atRuleName() {
|
||||
return 'charset';
|
||||
}
|
||||
|
||||
public function atRuleArgs() {
|
||||
return $this->sCharset;
|
||||
}
|
||||
|
||||
public function addComments(array $aComments) {
|
||||
$this->aComments = array_merge($this->aComments, $aComments);
|
||||
}
|
||||
|
||||
public function getComments() {
|
||||
return $this->aComments;
|
||||
}
|
||||
|
||||
public function setComments(array $aComments) {
|
||||
$this->aComments = $aComments;
|
||||
}
|
||||
}
|
||||
69
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/Import.php
vendored
Normal file
69
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/Import.php
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Property;
|
||||
|
||||
use Sabberworm\CSS\Value\URL;
|
||||
|
||||
/**
|
||||
* Class representing an @import rule.
|
||||
*/
|
||||
class Import implements AtRule {
|
||||
private $oLocation;
|
||||
private $sMediaQuery;
|
||||
protected $iLineNo;
|
||||
protected $aComments;
|
||||
|
||||
public function __construct(URL $oLocation, $sMediaQuery, $iLineNo = 0) {
|
||||
$this->oLocation = $oLocation;
|
||||
$this->sMediaQuery = $sMediaQuery;
|
||||
$this->iLineNo = $iLineNo;
|
||||
$this->aComments = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
public function setLocation($oLocation) {
|
||||
$this->oLocation = $oLocation;
|
||||
}
|
||||
|
||||
public function getLocation() {
|
||||
return $this->oLocation;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
return "@import ".$this->oLocation->render($oOutputFormat).($this->sMediaQuery === null ? '' : ' '.$this->sMediaQuery).';';
|
||||
}
|
||||
|
||||
public function atRuleName() {
|
||||
return 'import';
|
||||
}
|
||||
|
||||
public function atRuleArgs() {
|
||||
$aResult = array($this->oLocation);
|
||||
if($this->sMediaQuery) {
|
||||
array_push($aResult, $this->sMediaQuery);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function addComments(array $aComments) {
|
||||
$this->aComments = array_merge($this->aComments, $aComments);
|
||||
}
|
||||
|
||||
public function getComments() {
|
||||
return $this->aComments;
|
||||
}
|
||||
|
||||
public function setComments(array $aComments) {
|
||||
$this->aComments = $aComments;
|
||||
}
|
||||
}
|
||||
74
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/Selector.php
vendored
Normal file
74
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Property/Selector.php
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Property;
|
||||
|
||||
/**
|
||||
* Class representing a single CSS selector. Selectors have to be split by the comma prior to being passed into this class.
|
||||
*/
|
||||
class Selector {
|
||||
|
||||
//Regexes for specificity calculations
|
||||
const NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX = '/
|
||||
(\.[\w]+) # classes
|
||||
|
|
||||
\[(\w+) # attributes
|
||||
|
|
||||
(\:( # pseudo classes
|
||||
link|visited|active
|
||||
|hover|focus
|
||||
|lang
|
||||
|target
|
||||
|enabled|disabled|checked|indeterminate
|
||||
|root
|
||||
|nth-child|nth-last-child|nth-of-type|nth-last-of-type
|
||||
|first-child|last-child|first-of-type|last-of-type
|
||||
|only-child|only-of-type
|
||||
|empty|contains
|
||||
))
|
||||
/ix';
|
||||
|
||||
const ELEMENTS_AND_PSEUDO_ELEMENTS_RX = '/
|
||||
((^|[\s\+\>\~]+)[\w]+ # elements
|
||||
|
|
||||
\:{1,2}( # pseudo-elements
|
||||
after|before|first-letter|first-line|selection
|
||||
))
|
||||
/ix';
|
||||
|
||||
private $sSelector;
|
||||
private $iSpecificity;
|
||||
|
||||
public function __construct($sSelector, $bCalculateSpecificity = false) {
|
||||
$this->setSelector($sSelector);
|
||||
if ($bCalculateSpecificity) {
|
||||
$this->getSpecificity();
|
||||
}
|
||||
}
|
||||
|
||||
public function getSelector() {
|
||||
return $this->sSelector;
|
||||
}
|
||||
|
||||
public function setSelector($sSelector) {
|
||||
$this->sSelector = trim($sSelector);
|
||||
$this->iSpecificity = null;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->getSelector();
|
||||
}
|
||||
|
||||
public function getSpecificity() {
|
||||
if ($this->iSpecificity === null) {
|
||||
$a = 0;
|
||||
/// @todo should exclude \# as well as "#"
|
||||
$aMatches = null;
|
||||
$b = substr_count($this->sSelector, '#');
|
||||
$c = preg_match_all(self::NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX, $this->sSelector, $aMatches);
|
||||
$d = preg_match_all(self::ELEMENTS_AND_PSEUDO_ELEMENTS_RX, $this->sSelector, $aMatches);
|
||||
$this->iSpecificity = ($a * 1000) + ($b * 100) + ($c * 10) + $d;
|
||||
}
|
||||
return $this->iSpecificity;
|
||||
}
|
||||
|
||||
}
|
||||
9
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Renderable.php
vendored
Normal file
9
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Renderable.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS;
|
||||
|
||||
interface Renderable {
|
||||
public function __toString();
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat);
|
||||
public function getLineNo();
|
||||
}
|
||||
236
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Rule/Rule.php
vendored
Normal file
236
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Rule/Rule.php
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Rule;
|
||||
|
||||
use Sabberworm\CSS\Comment\Commentable;
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Renderable;
|
||||
use Sabberworm\CSS\Value\RuleValueList;
|
||||
use Sabberworm\CSS\Value\Value;
|
||||
|
||||
/**
|
||||
* RuleSets contains Rule objects which always have a key and a value.
|
||||
* In CSS, Rules are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];”
|
||||
*/
|
||||
class Rule implements Renderable, Commentable {
|
||||
|
||||
private $sRule;
|
||||
private $mValue;
|
||||
private $bIsImportant;
|
||||
private $aIeHack;
|
||||
protected $iLineNo;
|
||||
protected $aComments;
|
||||
|
||||
public function __construct($sRule, $iLineNo = 0) {
|
||||
$this->sRule = $sRule;
|
||||
$this->mValue = null;
|
||||
$this->bIsImportant = false;
|
||||
$this->aIeHack = array();
|
||||
$this->iLineNo = $iLineNo;
|
||||
$this->aComments = array();
|
||||
}
|
||||
|
||||
public static function parse(ParserState $oParserState) {
|
||||
$aComments = $oParserState->consumeWhiteSpace();
|
||||
$oRule = new Rule($oParserState->parseIdentifier(), $oParserState->currentLine());
|
||||
$oRule->setComments($aComments);
|
||||
$oRule->addComments($oParserState->consumeWhiteSpace());
|
||||
$oParserState->consume(':');
|
||||
$oValue = Value::parseValue($oParserState, self::listDelimiterForRule($oRule->getRule()));
|
||||
$oRule->setValue($oValue);
|
||||
if ($oParserState->getSettings()->bLenientParsing) {
|
||||
while ($oParserState->comes('\\')) {
|
||||
$oParserState->consume('\\');
|
||||
$oRule->addIeHack($oParserState->consume());
|
||||
$oParserState->consumeWhiteSpace();
|
||||
}
|
||||
}
|
||||
$oParserState->consumeWhiteSpace();
|
||||
if ($oParserState->comes('!')) {
|
||||
$oParserState->consume('!');
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$oParserState->consume('important');
|
||||
$oRule->setIsImportant(true);
|
||||
}
|
||||
$oParserState->consumeWhiteSpace();
|
||||
while ($oParserState->comes(';')) {
|
||||
$oParserState->consume(';');
|
||||
}
|
||||
$oParserState->consumeWhiteSpace();
|
||||
|
||||
return $oRule;
|
||||
}
|
||||
|
||||
private static function listDelimiterForRule($sRule) {
|
||||
if (preg_match('/^font($|-)/', $sRule)) {
|
||||
return array(',', '/', ' ');
|
||||
}
|
||||
return array(',', ' ', '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
public function setRule($sRule) {
|
||||
$this->sRule = $sRule;
|
||||
}
|
||||
|
||||
public function getRule() {
|
||||
return $this->sRule;
|
||||
}
|
||||
|
||||
public function getValue() {
|
||||
return $this->mValue;
|
||||
}
|
||||
|
||||
public function setValue($mValue) {
|
||||
$this->mValue = $mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Old-Style 2-dimensional array given. Retained for (some) backwards-compatibility. Use setValue() instead and wrapp the value inside a RuleValueList if necessary.
|
||||
*/
|
||||
public function setValues($aSpaceSeparatedValues) {
|
||||
$oSpaceSeparatedList = null;
|
||||
if (count($aSpaceSeparatedValues) > 1) {
|
||||
$oSpaceSeparatedList = new RuleValueList(' ', $this->iLineNo);
|
||||
}
|
||||
foreach ($aSpaceSeparatedValues as $aCommaSeparatedValues) {
|
||||
$oCommaSeparatedList = null;
|
||||
if (count($aCommaSeparatedValues) > 1) {
|
||||
$oCommaSeparatedList = new RuleValueList(',', $this->iLineNo);
|
||||
}
|
||||
foreach ($aCommaSeparatedValues as $mValue) {
|
||||
if (!$oSpaceSeparatedList && !$oCommaSeparatedList) {
|
||||
$this->mValue = $mValue;
|
||||
return $mValue;
|
||||
}
|
||||
if ($oCommaSeparatedList) {
|
||||
$oCommaSeparatedList->addListComponent($mValue);
|
||||
} else {
|
||||
$oSpaceSeparatedList->addListComponent($mValue);
|
||||
}
|
||||
}
|
||||
if (!$oSpaceSeparatedList) {
|
||||
$this->mValue = $oCommaSeparatedList;
|
||||
return $oCommaSeparatedList;
|
||||
} else {
|
||||
$oSpaceSeparatedList->addListComponent($oCommaSeparatedList);
|
||||
}
|
||||
}
|
||||
$this->mValue = $oSpaceSeparatedList;
|
||||
return $oSpaceSeparatedList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Old-Style 2-dimensional array returned. Retained for (some) backwards-compatibility. Use getValue() instead and check for the existance of a (nested set of) ValueList object(s).
|
||||
*/
|
||||
public function getValues() {
|
||||
if (!$this->mValue instanceof RuleValueList) {
|
||||
return array(array($this->mValue));
|
||||
}
|
||||
if ($this->mValue->getListSeparator() === ',') {
|
||||
return array($this->mValue->getListComponents());
|
||||
}
|
||||
$aResult = array();
|
||||
foreach ($this->mValue->getListComponents() as $mValue) {
|
||||
if (!$mValue instanceof RuleValueList || $mValue->getListSeparator() !== ',') {
|
||||
$aResult[] = array($mValue);
|
||||
continue;
|
||||
}
|
||||
if ($this->mValue->getListSeparator() === ' ' || count($aResult) === 0) {
|
||||
$aResult[] = array();
|
||||
}
|
||||
foreach ($mValue->getListComponents() as $mValue) {
|
||||
$aResult[count($aResult) - 1][] = $mValue;
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to the existing value. Value will be appended if a RuleValueList exists of the given type. Otherwise, the existing value will be wrapped by one.
|
||||
*/
|
||||
public function addValue($mValue, $sType = ' ') {
|
||||
if (!is_array($mValue)) {
|
||||
$mValue = array($mValue);
|
||||
}
|
||||
if (!$this->mValue instanceof RuleValueList || $this->mValue->getListSeparator() !== $sType) {
|
||||
$mCurrentValue = $this->mValue;
|
||||
$this->mValue = new RuleValueList($sType, $this->iLineNo);
|
||||
if ($mCurrentValue) {
|
||||
$this->mValue->addListComponent($mCurrentValue);
|
||||
}
|
||||
}
|
||||
foreach ($mValue as $mValueItem) {
|
||||
$this->mValue->addListComponent($mValueItem);
|
||||
}
|
||||
}
|
||||
|
||||
public function addIeHack($iModifier) {
|
||||
$this->aIeHack[] = $iModifier;
|
||||
}
|
||||
|
||||
public function setIeHack(array $aModifiers) {
|
||||
$this->aIeHack = $aModifiers;
|
||||
}
|
||||
|
||||
public function getIeHack() {
|
||||
return $this->aIeHack;
|
||||
}
|
||||
|
||||
public function setIsImportant($bIsImportant) {
|
||||
$this->bIsImportant = $bIsImportant;
|
||||
}
|
||||
|
||||
public function getIsImportant() {
|
||||
return $this->bIsImportant;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$sResult = "{$this->sRule}:{$oOutputFormat->spaceAfterRuleName()}";
|
||||
if ($this->mValue instanceof Value) { //Can also be a ValueList
|
||||
$sResult .= $this->mValue->render($oOutputFormat);
|
||||
} else {
|
||||
$sResult .= $this->mValue;
|
||||
}
|
||||
if (!empty($this->aIeHack)) {
|
||||
$sResult .= ' \\' . implode('\\', $this->aIeHack);
|
||||
}
|
||||
if ($this->bIsImportant) {
|
||||
$sResult .= ' !important';
|
||||
}
|
||||
$sResult .= ';';
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aComments Array of comments.
|
||||
*/
|
||||
public function addComments(array $aComments) {
|
||||
$this->aComments = array_merge($this->aComments, $aComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getComments() {
|
||||
return $this->aComments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aComments Array containing Comment objects.
|
||||
*/
|
||||
public function setComments(array $aComments) {
|
||||
$this->aComments = $aComments;
|
||||
}
|
||||
|
||||
}
|
||||
44
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/RuleSet/AtRuleSet.php
vendored
Normal file
44
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/RuleSet/AtRuleSet.php
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\RuleSet;
|
||||
|
||||
use Sabberworm\CSS\Property\AtRule;
|
||||
|
||||
/**
|
||||
* A RuleSet constructed by an unknown @-rule. @font-face rules are rendered into AtRuleSet objects.
|
||||
*/
|
||||
class AtRuleSet extends RuleSet implements AtRule {
|
||||
|
||||
private $sType;
|
||||
private $sArgs;
|
||||
|
||||
public function __construct($sType, $sArgs = '', $iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
$this->sType = $sType;
|
||||
$this->sArgs = $sArgs;
|
||||
}
|
||||
|
||||
public function atRuleName() {
|
||||
return $this->sType;
|
||||
}
|
||||
|
||||
public function atRuleArgs() {
|
||||
return $this->sArgs;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$sArgs = $this->sArgs;
|
||||
if($sArgs) {
|
||||
$sArgs = ' ' . $sArgs;
|
||||
}
|
||||
$sResult = "@{$this->sType}$sArgs{$oOutputFormat->spaceBeforeOpeningBrace()}{";
|
||||
$sResult .= parent::render($oOutputFormat);
|
||||
$sResult .= '}';
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
}
|
||||
628
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/RuleSet/DeclarationBlock.php
vendored
Normal file
628
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/RuleSet/DeclarationBlock.php
vendored
Normal file
@@ -0,0 +1,628 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\RuleSet;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\OutputException;
|
||||
use Sabberworm\CSS\Property\Selector;
|
||||
use Sabberworm\CSS\Rule\Rule;
|
||||
use Sabberworm\CSS\Value\RuleValueList;
|
||||
use Sabberworm\CSS\Value\Value;
|
||||
use Sabberworm\CSS\Value\Size;
|
||||
use Sabberworm\CSS\Value\Color;
|
||||
use Sabberworm\CSS\Value\URL;
|
||||
|
||||
/**
|
||||
* Declaration blocks are the parts of a css file which denote the rules belonging to a selector.
|
||||
* Declaration blocks usually appear directly inside a Document or another CSSList (mostly a MediaQuery).
|
||||
*/
|
||||
class DeclarationBlock extends RuleSet {
|
||||
|
||||
private $aSelectors;
|
||||
|
||||
public function __construct($iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
$this->aSelectors = array();
|
||||
}
|
||||
|
||||
public static function parse(ParserState $oParserState) {
|
||||
$aComments = array();
|
||||
$oResult = new DeclarationBlock($oParserState->currentLine());
|
||||
$oResult->setSelector($oParserState->consumeUntil('{', false, true, $aComments));
|
||||
$oResult->setComments($aComments);
|
||||
RuleSet::parseRuleSet($oParserState, $oResult);
|
||||
return $oResult;
|
||||
}
|
||||
|
||||
|
||||
public function setSelectors($mSelector) {
|
||||
if (is_array($mSelector)) {
|
||||
$this->aSelectors = $mSelector;
|
||||
} else {
|
||||
$this->aSelectors = explode(',', $mSelector);
|
||||
}
|
||||
foreach ($this->aSelectors as $iKey => $mSelector) {
|
||||
if (!($mSelector instanceof Selector)) {
|
||||
$this->aSelectors[$iKey] = new Selector($mSelector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove one of the selector of the block
|
||||
public function removeSelector($mSelector) {
|
||||
if($mSelector instanceof Selector) {
|
||||
$mSelector = $mSelector->getSelector();
|
||||
}
|
||||
foreach($this->aSelectors as $iKey => $oSelector) {
|
||||
if($oSelector->getSelector() === $mSelector) {
|
||||
unset($this->aSelectors[$iKey]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use getSelectors()
|
||||
*/
|
||||
public function getSelector() {
|
||||
return $this->getSelectors();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use setSelectors()
|
||||
*/
|
||||
public function setSelector($mSelector) {
|
||||
$this->setSelectors($mSelector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get selectors.
|
||||
*
|
||||
* @return Selector[] Selectors.
|
||||
*/
|
||||
public function getSelectors() {
|
||||
return $this->aSelectors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Split shorthand declarations (e.g. +margin+ or +font+) into their constituent parts.
|
||||
* */
|
||||
public function expandShorthands() {
|
||||
// border must be expanded before dimensions
|
||||
$this->expandBorderShorthand();
|
||||
$this->expandDimensionsShorthand();
|
||||
$this->expandFontShorthand();
|
||||
$this->expandBackgroundShorthand();
|
||||
$this->expandListStyleShorthand();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create shorthand declarations (e.g. +margin+ or +font+) whenever possible.
|
||||
* */
|
||||
public function createShorthands() {
|
||||
$this->createBackgroundShorthand();
|
||||
$this->createDimensionsShorthand();
|
||||
// border must be shortened after dimensions
|
||||
$this->createBorderShorthand();
|
||||
$this->createFontShorthand();
|
||||
$this->createListStyleShorthand();
|
||||
}
|
||||
|
||||
/**
|
||||
* Split shorthand border declarations (e.g. <tt>border: 1px red;</tt>)
|
||||
* Additional splitting happens in expandDimensionsShorthand
|
||||
* Multiple borders are not yet supported as of 3
|
||||
* */
|
||||
public function expandBorderShorthand() {
|
||||
$aBorderRules = array(
|
||||
'border', 'border-left', 'border-right', 'border-top', 'border-bottom'
|
||||
);
|
||||
$aBorderSizes = array(
|
||||
'thin', 'medium', 'thick'
|
||||
);
|
||||
$aRules = $this->getRulesAssoc();
|
||||
foreach ($aBorderRules as $sBorderRule) {
|
||||
if (!isset($aRules[$sBorderRule]))
|
||||
continue;
|
||||
$oRule = $aRules[$sBorderRule];
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
foreach ($aValues as $mValue) {
|
||||
if ($mValue instanceof Value) {
|
||||
$mNewValue = clone $mValue;
|
||||
} else {
|
||||
$mNewValue = $mValue;
|
||||
}
|
||||
if ($mValue instanceof Size) {
|
||||
$sNewRuleName = $sBorderRule . "-width";
|
||||
} else if ($mValue instanceof Color) {
|
||||
$sNewRuleName = $sBorderRule . "-color";
|
||||
} else {
|
||||
if (in_array($mValue, $aBorderSizes)) {
|
||||
$sNewRuleName = $sBorderRule . "-width";
|
||||
} else/* if(in_array($mValue, $aBorderStyles)) */ {
|
||||
$sNewRuleName = $sBorderRule . "-style";
|
||||
}
|
||||
}
|
||||
$oNewRule = new Rule($sNewRuleName, $this->iLineNo);
|
||||
$oNewRule->setIsImportant($oRule->getIsImportant());
|
||||
$oNewRule->addValue(array($mNewValue));
|
||||
$this->addRule($oNewRule);
|
||||
}
|
||||
$this->removeRule($sBorderRule);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Split shorthand dimensional declarations (e.g. <tt>margin: 0px auto;</tt>)
|
||||
* into their constituent parts.
|
||||
* Handles margin, padding, border-color, border-style and border-width.
|
||||
* */
|
||||
public function expandDimensionsShorthand() {
|
||||
$aExpansions = array(
|
||||
'margin' => 'margin-%s',
|
||||
'padding' => 'padding-%s',
|
||||
'border-color' => 'border-%s-color',
|
||||
'border-style' => 'border-%s-style',
|
||||
'border-width' => 'border-%s-width'
|
||||
);
|
||||
$aRules = $this->getRulesAssoc();
|
||||
foreach ($aExpansions as $sProperty => $sExpanded) {
|
||||
if (!isset($aRules[$sProperty]))
|
||||
continue;
|
||||
$oRule = $aRules[$sProperty];
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
$top = $right = $bottom = $left = null;
|
||||
switch (count($aValues)) {
|
||||
case 1:
|
||||
$top = $right = $bottom = $left = $aValues[0];
|
||||
break;
|
||||
case 2:
|
||||
$top = $bottom = $aValues[0];
|
||||
$left = $right = $aValues[1];
|
||||
break;
|
||||
case 3:
|
||||
$top = $aValues[0];
|
||||
$left = $right = $aValues[1];
|
||||
$bottom = $aValues[2];
|
||||
break;
|
||||
case 4:
|
||||
$top = $aValues[0];
|
||||
$right = $aValues[1];
|
||||
$bottom = $aValues[2];
|
||||
$left = $aValues[3];
|
||||
break;
|
||||
}
|
||||
foreach (array('top', 'right', 'bottom', 'left') as $sPosition) {
|
||||
$oNewRule = new Rule(sprintf($sExpanded, $sPosition), $this->iLineNo);
|
||||
$oNewRule->setIsImportant($oRule->getIsImportant());
|
||||
$oNewRule->addValue(${$sPosition});
|
||||
$this->addRule($oNewRule);
|
||||
}
|
||||
$this->removeRule($sProperty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert shorthand font declarations
|
||||
* (e.g. <tt>font: 300 italic 11px/14px verdana, helvetica, sans-serif;</tt>)
|
||||
* into their constituent parts.
|
||||
* */
|
||||
public function expandFontShorthand() {
|
||||
$aRules = $this->getRulesAssoc();
|
||||
if (!isset($aRules['font']))
|
||||
return;
|
||||
$oRule = $aRules['font'];
|
||||
// reset properties to 'normal' per http://www.w3.org/TR/21/fonts.html#font-shorthand
|
||||
$aFontProperties = array(
|
||||
'font-style' => 'normal',
|
||||
'font-variant' => 'normal',
|
||||
'font-weight' => 'normal',
|
||||
'font-size' => 'normal',
|
||||
'line-height' => 'normal'
|
||||
);
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
foreach ($aValues as $mValue) {
|
||||
if (!$mValue instanceof Value) {
|
||||
$mValue = mb_strtolower($mValue);
|
||||
}
|
||||
if (in_array($mValue, array('normal', 'inherit'))) {
|
||||
foreach (array('font-style', 'font-weight', 'font-variant') as $sProperty) {
|
||||
if (!isset($aFontProperties[$sProperty])) {
|
||||
$aFontProperties[$sProperty] = $mValue;
|
||||
}
|
||||
}
|
||||
} else if (in_array($mValue, array('italic', 'oblique'))) {
|
||||
$aFontProperties['font-style'] = $mValue;
|
||||
} else if ($mValue == 'small-caps') {
|
||||
$aFontProperties['font-variant'] = $mValue;
|
||||
} else if (
|
||||
in_array($mValue, array('bold', 'bolder', 'lighter'))
|
||||
|| ($mValue instanceof Size
|
||||
&& in_array($mValue->getSize(), range(100, 900, 100)))
|
||||
) {
|
||||
$aFontProperties['font-weight'] = $mValue;
|
||||
} else if ($mValue instanceof RuleValueList && $mValue->getListSeparator() == '/') {
|
||||
list($oSize, $oHeight) = $mValue->getListComponents();
|
||||
$aFontProperties['font-size'] = $oSize;
|
||||
$aFontProperties['line-height'] = $oHeight;
|
||||
} else if ($mValue instanceof Size && $mValue->getUnit() !== null) {
|
||||
$aFontProperties['font-size'] = $mValue;
|
||||
} else {
|
||||
$aFontProperties['font-family'] = $mValue;
|
||||
}
|
||||
}
|
||||
foreach ($aFontProperties as $sProperty => $mValue) {
|
||||
$oNewRule = new Rule($sProperty, $this->iLineNo);
|
||||
$oNewRule->addValue($mValue);
|
||||
$oNewRule->setIsImportant($oRule->getIsImportant());
|
||||
$this->addRule($oNewRule);
|
||||
}
|
||||
$this->removeRule('font');
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert shorthand background declarations
|
||||
* (e.g. <tt>background: url("chess.png") gray 50% repeat fixed;</tt>)
|
||||
* into their constituent parts.
|
||||
* @see http://www.w3.org/TR/21/colors.html#propdef-background
|
||||
* */
|
||||
|
||||
public function expandBackgroundShorthand() {
|
||||
$aRules = $this->getRulesAssoc();
|
||||
if (!isset($aRules['background']))
|
||||
return;
|
||||
$oRule = $aRules['background'];
|
||||
$aBgProperties = array(
|
||||
'background-color' => array('transparent'), 'background-image' => array('none'),
|
||||
'background-repeat' => array('repeat'), 'background-attachment' => array('scroll'),
|
||||
'background-position' => array(new Size(0, '%', null, false, $this->iLineNo), new Size(0, '%', null, false, $this->iLineNo))
|
||||
);
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
if (count($aValues) == 1 && $aValues[0] == 'inherit') {
|
||||
foreach ($aBgProperties as $sProperty => $mValue) {
|
||||
$oNewRule = new Rule($sProperty, $this->iLineNo);
|
||||
$oNewRule->addValue('inherit');
|
||||
$oNewRule->setIsImportant($oRule->getIsImportant());
|
||||
$this->addRule($oNewRule);
|
||||
}
|
||||
$this->removeRule('background');
|
||||
return;
|
||||
}
|
||||
$iNumBgPos = 0;
|
||||
foreach ($aValues as $mValue) {
|
||||
if (!$mValue instanceof Value) {
|
||||
$mValue = mb_strtolower($mValue);
|
||||
}
|
||||
if ($mValue instanceof URL) {
|
||||
$aBgProperties['background-image'] = $mValue;
|
||||
} else if ($mValue instanceof Color) {
|
||||
$aBgProperties['background-color'] = $mValue;
|
||||
} else if (in_array($mValue, array('scroll', 'fixed'))) {
|
||||
$aBgProperties['background-attachment'] = $mValue;
|
||||
} else if (in_array($mValue, array('repeat', 'no-repeat', 'repeat-x', 'repeat-y'))) {
|
||||
$aBgProperties['background-repeat'] = $mValue;
|
||||
} else if (in_array($mValue, array('left', 'center', 'right', 'top', 'bottom'))
|
||||
|| $mValue instanceof Size
|
||||
) {
|
||||
if ($iNumBgPos == 0) {
|
||||
$aBgProperties['background-position'][0] = $mValue;
|
||||
$aBgProperties['background-position'][1] = 'center';
|
||||
} else {
|
||||
$aBgProperties['background-position'][$iNumBgPos] = $mValue;
|
||||
}
|
||||
$iNumBgPos++;
|
||||
}
|
||||
}
|
||||
foreach ($aBgProperties as $sProperty => $mValue) {
|
||||
$oNewRule = new Rule($sProperty, $this->iLineNo);
|
||||
$oNewRule->setIsImportant($oRule->getIsImportant());
|
||||
$oNewRule->addValue($mValue);
|
||||
$this->addRule($oNewRule);
|
||||
}
|
||||
$this->removeRule('background');
|
||||
}
|
||||
|
||||
public function expandListStyleShorthand() {
|
||||
$aListProperties = array(
|
||||
'list-style-type' => 'disc',
|
||||
'list-style-position' => 'outside',
|
||||
'list-style-image' => 'none'
|
||||
);
|
||||
$aListStyleTypes = array(
|
||||
'none', 'disc', 'circle', 'square', 'decimal-leading-zero', 'decimal',
|
||||
'lower-roman', 'upper-roman', 'lower-greek', 'lower-alpha', 'lower-latin',
|
||||
'upper-alpha', 'upper-latin', 'hebrew', 'armenian', 'georgian', 'cjk-ideographic',
|
||||
'hiragana', 'hira-gana-iroha', 'katakana-iroha', 'katakana'
|
||||
);
|
||||
$aListStylePositions = array(
|
||||
'inside', 'outside'
|
||||
);
|
||||
$aRules = $this->getRulesAssoc();
|
||||
if (!isset($aRules['list-style']))
|
||||
return;
|
||||
$oRule = $aRules['list-style'];
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
if (count($aValues) == 1 && $aValues[0] == 'inherit') {
|
||||
foreach ($aListProperties as $sProperty => $mValue) {
|
||||
$oNewRule = new Rule($sProperty, $this->iLineNo);
|
||||
$oNewRule->addValue('inherit');
|
||||
$oNewRule->setIsImportant($oRule->getIsImportant());
|
||||
$this->addRule($oNewRule);
|
||||
}
|
||||
$this->removeRule('list-style');
|
||||
return;
|
||||
}
|
||||
foreach ($aValues as $mValue) {
|
||||
if (!$mValue instanceof Value) {
|
||||
$mValue = mb_strtolower($mValue);
|
||||
}
|
||||
if ($mValue instanceof Url) {
|
||||
$aListProperties['list-style-image'] = $mValue;
|
||||
} else if (in_array($mValue, $aListStyleTypes)) {
|
||||
$aListProperties['list-style-types'] = $mValue;
|
||||
} else if (in_array($mValue, $aListStylePositions)) {
|
||||
$aListProperties['list-style-position'] = $mValue;
|
||||
}
|
||||
}
|
||||
foreach ($aListProperties as $sProperty => $mValue) {
|
||||
$oNewRule = new Rule($sProperty, $this->iLineNo);
|
||||
$oNewRule->setIsImportant($oRule->getIsImportant());
|
||||
$oNewRule->addValue($mValue);
|
||||
$this->addRule($oNewRule);
|
||||
}
|
||||
$this->removeRule('list-style');
|
||||
}
|
||||
|
||||
public function createShorthandProperties(array $aProperties, $sShorthand) {
|
||||
$aRules = $this->getRulesAssoc();
|
||||
$aNewValues = array();
|
||||
foreach ($aProperties as $sProperty) {
|
||||
if (!isset($aRules[$sProperty]))
|
||||
continue;
|
||||
$oRule = $aRules[$sProperty];
|
||||
if (!$oRule->getIsImportant()) {
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
foreach ($aValues as $mValue) {
|
||||
$aNewValues[] = $mValue;
|
||||
}
|
||||
$this->removeRule($sProperty);
|
||||
}
|
||||
}
|
||||
if (count($aNewValues)) {
|
||||
$oNewRule = new Rule($sShorthand, $this->iLineNo);
|
||||
foreach ($aNewValues as $mValue) {
|
||||
$oNewRule->addValue($mValue);
|
||||
}
|
||||
$this->addRule($oNewRule);
|
||||
}
|
||||
}
|
||||
|
||||
public function createBackgroundShorthand() {
|
||||
$aProperties = array(
|
||||
'background-color', 'background-image', 'background-repeat',
|
||||
'background-position', 'background-attachment'
|
||||
);
|
||||
$this->createShorthandProperties($aProperties, 'background');
|
||||
}
|
||||
|
||||
public function createListStyleShorthand() {
|
||||
$aProperties = array(
|
||||
'list-style-type', 'list-style-position', 'list-style-image'
|
||||
);
|
||||
$this->createShorthandProperties($aProperties, 'list-style');
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine border-color, border-style and border-width into border
|
||||
* Should be run after create_dimensions_shorthand!
|
||||
* */
|
||||
public function createBorderShorthand() {
|
||||
$aProperties = array(
|
||||
'border-width', 'border-style', 'border-color'
|
||||
);
|
||||
$this->createShorthandProperties($aProperties, 'border');
|
||||
}
|
||||
|
||||
/*
|
||||
* Looks for long format CSS dimensional properties
|
||||
* (margin, padding, border-color, border-style and border-width)
|
||||
* and converts them into shorthand CSS properties.
|
||||
* */
|
||||
|
||||
public function createDimensionsShorthand() {
|
||||
$aPositions = array('top', 'right', 'bottom', 'left');
|
||||
$aExpansions = array(
|
||||
'margin' => 'margin-%s',
|
||||
'padding' => 'padding-%s',
|
||||
'border-color' => 'border-%s-color',
|
||||
'border-style' => 'border-%s-style',
|
||||
'border-width' => 'border-%s-width'
|
||||
);
|
||||
$aRules = $this->getRulesAssoc();
|
||||
foreach ($aExpansions as $sProperty => $sExpanded) {
|
||||
$aFoldable = array();
|
||||
foreach ($aRules as $sRuleName => $oRule) {
|
||||
foreach ($aPositions as $sPosition) {
|
||||
if ($sRuleName == sprintf($sExpanded, $sPosition)) {
|
||||
$aFoldable[$sRuleName] = $oRule;
|
||||
}
|
||||
}
|
||||
}
|
||||
// All four dimensions must be present
|
||||
if (count($aFoldable) == 4) {
|
||||
$aValues = array();
|
||||
foreach ($aPositions as $sPosition) {
|
||||
$oRule = $aRules[sprintf($sExpanded, $sPosition)];
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aRuleValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aRuleValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aRuleValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
$aValues[$sPosition] = $aRuleValues;
|
||||
}
|
||||
$oNewRule = new Rule($sProperty, $this->iLineNo);
|
||||
if ((string) $aValues['left'][0] == (string) $aValues['right'][0]) {
|
||||
if ((string) $aValues['top'][0] == (string) $aValues['bottom'][0]) {
|
||||
if ((string) $aValues['top'][0] == (string) $aValues['left'][0]) {
|
||||
// All 4 sides are equal
|
||||
$oNewRule->addValue($aValues['top']);
|
||||
} else {
|
||||
// Top and bottom are equal, left and right are equal
|
||||
$oNewRule->addValue($aValues['top']);
|
||||
$oNewRule->addValue($aValues['left']);
|
||||
}
|
||||
} else {
|
||||
// Only left and right are equal
|
||||
$oNewRule->addValue($aValues['top']);
|
||||
$oNewRule->addValue($aValues['left']);
|
||||
$oNewRule->addValue($aValues['bottom']);
|
||||
}
|
||||
} else {
|
||||
// No sides are equal
|
||||
$oNewRule->addValue($aValues['top']);
|
||||
$oNewRule->addValue($aValues['left']);
|
||||
$oNewRule->addValue($aValues['bottom']);
|
||||
$oNewRule->addValue($aValues['right']);
|
||||
}
|
||||
$this->addRule($oNewRule);
|
||||
foreach ($aPositions as $sPosition) {
|
||||
$this->removeRule(sprintf($sExpanded, $sPosition));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for long format CSS font properties (e.g. <tt>font-weight</tt>) and
|
||||
* tries to convert them into a shorthand CSS <tt>font</tt> property.
|
||||
* At least font-size AND font-family must be present in order to create a shorthand declaration.
|
||||
* */
|
||||
public function createFontShorthand() {
|
||||
$aFontProperties = array(
|
||||
'font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family'
|
||||
);
|
||||
$aRules = $this->getRulesAssoc();
|
||||
if (!isset($aRules['font-size']) || !isset($aRules['font-family'])) {
|
||||
return;
|
||||
}
|
||||
$oNewRule = new Rule('font', $this->iLineNo);
|
||||
foreach (array('font-style', 'font-variant', 'font-weight') as $sProperty) {
|
||||
if (isset($aRules[$sProperty])) {
|
||||
$oRule = $aRules[$sProperty];
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
if ($aValues[0] !== 'normal') {
|
||||
$oNewRule->addValue($aValues[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Get the font-size value
|
||||
$oRule = $aRules['font-size'];
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aFSValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aFSValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aFSValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
// But wait to know if we have line-height to add it
|
||||
if (isset($aRules['line-height'])) {
|
||||
$oRule = $aRules['line-height'];
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aLHValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aLHValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aLHValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
if ($aLHValues[0] !== 'normal') {
|
||||
$val = new RuleValueList('/', $this->iLineNo);
|
||||
$val->addListComponent($aFSValues[0]);
|
||||
$val->addListComponent($aLHValues[0]);
|
||||
$oNewRule->addValue($val);
|
||||
}
|
||||
} else {
|
||||
$oNewRule->addValue($aFSValues[0]);
|
||||
}
|
||||
$oRule = $aRules['font-family'];
|
||||
$mRuleValue = $oRule->getValue();
|
||||
$aFFValues = array();
|
||||
if (!$mRuleValue instanceof RuleValueList) {
|
||||
$aFFValues[] = $mRuleValue;
|
||||
} else {
|
||||
$aFFValues = $mRuleValue->getListComponents();
|
||||
}
|
||||
$oFFValue = new RuleValueList(',', $this->iLineNo);
|
||||
$oFFValue->setListComponents($aFFValues);
|
||||
$oNewRule->addValue($oFFValue);
|
||||
|
||||
$this->addRule($oNewRule);
|
||||
foreach ($aFontProperties as $sProperty) {
|
||||
$this->removeRule($sProperty);
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
if(count($this->aSelectors) === 0) {
|
||||
// If all the selectors have been removed, this declaration block becomes invalid
|
||||
throw new OutputException("Attempt to print declaration block with missing selector", $this->iLineNo);
|
||||
}
|
||||
$sResult = $oOutputFormat->sBeforeDeclarationBlock;
|
||||
$sResult .= $oOutputFormat->implode($oOutputFormat->spaceBeforeSelectorSeparator() . ',' . $oOutputFormat->spaceAfterSelectorSeparator(), $this->aSelectors);
|
||||
$sResult .= $oOutputFormat->sAfterDeclarationBlockSelectors;
|
||||
$sResult .= $oOutputFormat->spaceBeforeOpeningBrace() . '{';
|
||||
$sResult .= parent::render($oOutputFormat);
|
||||
$sResult .= '}';
|
||||
$sResult .= $oOutputFormat->sAfterDeclarationBlock;
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
}
|
||||
212
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/RuleSet/RuleSet.php
vendored
Normal file
212
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/RuleSet/RuleSet.php
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\RuleSet;
|
||||
|
||||
use Sabberworm\CSS\Comment\Commentable;
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
|
||||
use Sabberworm\CSS\Renderable;
|
||||
use Sabberworm\CSS\Rule\Rule;
|
||||
|
||||
/**
|
||||
* RuleSet is a generic superclass denoting rules. The typical example for rule sets are declaration block.
|
||||
* However, unknown At-Rules (like @font-face) are also rule sets.
|
||||
*/
|
||||
abstract class RuleSet implements Renderable, Commentable {
|
||||
|
||||
private $aRules;
|
||||
protected $iLineNo;
|
||||
protected $aComments;
|
||||
|
||||
public function __construct($iLineNo = 0) {
|
||||
$this->aRules = array();
|
||||
$this->iLineNo = $iLineNo;
|
||||
$this->aComments = array();
|
||||
}
|
||||
|
||||
public static function parseRuleSet(ParserState $oParserState, RuleSet $oRuleSet) {
|
||||
while ($oParserState->comes(';')) {
|
||||
$oParserState->consume(';');
|
||||
}
|
||||
while (!$oParserState->comes('}')) {
|
||||
$oRule = null;
|
||||
if($oParserState->getSettings()->bLenientParsing) {
|
||||
try {
|
||||
$oRule = Rule::parse($oParserState);
|
||||
} catch (UnexpectedTokenException $e) {
|
||||
try {
|
||||
$sConsume = $oParserState->consumeUntil(array("\n", ";", '}'), true);
|
||||
// We need to “unfind” the matches to the end of the ruleSet as this will be matched later
|
||||
if($oParserState->streql(substr($sConsume, -1), '}')) {
|
||||
$oParserState->backtrack(1);
|
||||
} else {
|
||||
while ($oParserState->comes(';')) {
|
||||
$oParserState->consume(';');
|
||||
}
|
||||
}
|
||||
} catch (UnexpectedTokenException $e) {
|
||||
// We’ve reached the end of the document. Just close the RuleSet.
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$oRule = Rule::parse($oParserState);
|
||||
}
|
||||
if($oRule) {
|
||||
$oRuleSet->addRule($oRule);
|
||||
}
|
||||
}
|
||||
$oParserState->consume('}');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
public function addRule(Rule $oRule, Rule $oSibling = null) {
|
||||
$sRule = $oRule->getRule();
|
||||
if(!isset($this->aRules[$sRule])) {
|
||||
$this->aRules[$sRule] = array();
|
||||
}
|
||||
|
||||
$iPosition = count($this->aRules[$sRule]);
|
||||
|
||||
if ($oSibling !== null) {
|
||||
$iSiblingPos = array_search($oSibling, $this->aRules[$sRule], true);
|
||||
if ($iSiblingPos !== false) {
|
||||
$iPosition = $iSiblingPos;
|
||||
}
|
||||
}
|
||||
|
||||
array_splice($this->aRules[$sRule], $iPosition, 0, array($oRule));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all rules matching the given rule name
|
||||
* @param (null|string|Rule) $mRule pattern to search for. If null, returns all rules. if the pattern ends with a dash, all rules starting with the pattern are returned as well as one matching the pattern with the dash excluded. passing a Rule behaves like calling getRules($mRule->getRule()).
|
||||
* @example $oRuleSet->getRules('font-') //returns an array of all rules either beginning with font- or matching font.
|
||||
* @example $oRuleSet->getRules('font') //returns array(0 => $oRule, …) or array().
|
||||
* @return Rule[] Rules.
|
||||
*/
|
||||
public function getRules($mRule = null) {
|
||||
if ($mRule instanceof Rule) {
|
||||
$mRule = $mRule->getRule();
|
||||
}
|
||||
$aResult = array();
|
||||
foreach($this->aRules as $sName => $aRules) {
|
||||
// Either no search rule is given or the search rule matches the found rule exactly or the search rule ends in “-” and the found rule starts with the search rule.
|
||||
if(!$mRule || $sName === $mRule || (strrpos($mRule, '-') === strlen($mRule) - strlen('-') && (strpos($sName, $mRule) === 0 || $sName === substr($mRule, 0, -1)))) {
|
||||
$aResult = array_merge($aResult, $aRules);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override all the rules of this set.
|
||||
* @param Rule[] $aRules The rules to override with.
|
||||
*/
|
||||
public function setRules(array $aRules) {
|
||||
$this->aRules = array();
|
||||
foreach ($aRules as $rule) {
|
||||
$this->addRule($rule);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all rules matching the given pattern and returns them in an associative array with the rule’s name as keys. This method exists mainly for backwards-compatibility and is really only partially useful.
|
||||
* @param (string) $mRule pattern to search for. If null, returns all rules. if the pattern ends with a dash, all rules starting with the pattern are returned as well as one matching the pattern with the dash excluded. passing a Rule behaves like calling getRules($mRule->getRule()).
|
||||
* Note: This method loses some information: Calling this (with an argument of 'background-') on a declaration block like { background-color: green; background-color; rgba(0, 127, 0, 0.7); } will only yield an associative array containing the rgba-valued rule while @link{getRules()} would yield an indexed array containing both.
|
||||
* @return Rule[] Rules.
|
||||
*/
|
||||
public function getRulesAssoc($mRule = null) {
|
||||
$aResult = array();
|
||||
foreach($this->getRules($mRule) as $oRule) {
|
||||
$aResult[$oRule->getRule()] = $oRule;
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a rule from this RuleSet. This accepts all the possible values that @link{getRules()} accepts. If given a Rule, it will only remove this particular rule (by identity). If given a name, it will remove all rules by that name. Note: this is different from pre-v.2.0 behaviour of PHP-CSS-Parser, where passing a Rule instance would remove all rules with the same name. To get the old behvaiour, use removeRule($oRule->getRule()).
|
||||
* @param (null|string|Rule) $mRule pattern to remove. If $mRule is null, all rules are removed. If the pattern ends in a dash, all rules starting with the pattern are removed as well as one matching the pattern with the dash excluded. Passing a Rule behaves matches by identity.
|
||||
*/
|
||||
public function removeRule($mRule) {
|
||||
if($mRule instanceof Rule) {
|
||||
$sRule = $mRule->getRule();
|
||||
if(!isset($this->aRules[$sRule])) {
|
||||
return;
|
||||
}
|
||||
foreach($this->aRules[$sRule] as $iKey => $oRule) {
|
||||
if($oRule === $mRule) {
|
||||
unset($this->aRules[$sRule][$iKey]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach($this->aRules as $sName => $aRules) {
|
||||
// Either no search rule is given or the search rule matches the found rule exactly or the search rule ends in “-” and the found rule starts with the search rule or equals it (without the trailing dash).
|
||||
if(!$mRule || $sName === $mRule || (strrpos($mRule, '-') === strlen($mRule) - strlen('-') && (strpos($sName, $mRule) === 0 || $sName === substr($mRule, 0, -1)))) {
|
||||
unset($this->aRules[$sName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$sResult = '';
|
||||
$bIsFirst = true;
|
||||
foreach ($this->aRules as $aRules) {
|
||||
foreach($aRules as $oRule) {
|
||||
$sRendered = $oOutputFormat->safely(function() use ($oRule, $oOutputFormat) {
|
||||
return $oRule->render($oOutputFormat->nextLevel());
|
||||
});
|
||||
if($sRendered === null) {
|
||||
continue;
|
||||
}
|
||||
if($bIsFirst) {
|
||||
$bIsFirst = false;
|
||||
$sResult .= $oOutputFormat->nextLevel()->spaceBeforeRules();
|
||||
} else {
|
||||
$sResult .= $oOutputFormat->nextLevel()->spaceBetweenRules();
|
||||
}
|
||||
$sResult .= $sRendered;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$bIsFirst) {
|
||||
// Had some output
|
||||
$sResult .= $oOutputFormat->spaceAfterRules();
|
||||
}
|
||||
|
||||
return $oOutputFormat->removeLastSemicolon($sResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aComments Array of comments.
|
||||
*/
|
||||
public function addComments(array $aComments) {
|
||||
$this->aComments = array_merge($this->aComments, $aComments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getComments() {
|
||||
return $this->aComments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aComments Array containing Comment objects.
|
||||
*/
|
||||
public function setComments(array $aComments) {
|
||||
$this->aComments = $aComments;
|
||||
}
|
||||
|
||||
}
|
||||
54
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Settings.php
vendored
Normal file
54
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Settings.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS;
|
||||
|
||||
use Sabberworm\CSS\Rule\Rule;
|
||||
|
||||
/**
|
||||
* Parser settings class.
|
||||
*
|
||||
* Configure parser behaviour here.
|
||||
*/
|
||||
class Settings {
|
||||
/**
|
||||
* Multi-byte string support. If true (mbstring extension must be enabled), will use (slower) mb_strlen, mb_convert_case, mb_substr and mb_strpos functions. Otherwise, the normal (ASCII-Only) functions will be used.
|
||||
*/
|
||||
public $bMultibyteSupport;
|
||||
|
||||
/**
|
||||
* The default charset for the CSS if no `@charset` rule is found. Defaults to utf-8.
|
||||
*/
|
||||
public $sDefaultCharset = 'utf-8';
|
||||
|
||||
/**
|
||||
* Lenient parsing. When used (which is true by default), the parser will not choke on unexpected tokens but simply ignore them.
|
||||
*/
|
||||
public $bLenientParsing = true;
|
||||
|
||||
private function __construct() {
|
||||
$this->bMultibyteSupport = extension_loaded('mbstring');
|
||||
}
|
||||
|
||||
public static function create() {
|
||||
return new Settings();
|
||||
}
|
||||
|
||||
public function withMultibyteSupport($bMultibyteSupport = true) {
|
||||
$this->bMultibyteSupport = $bMultibyteSupport;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withDefaultCharset($sDefaultCharset) {
|
||||
$this->sDefaultCharset = $sDefaultCharset;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withLenientParsing($bLenientParsing = true) {
|
||||
$this->bLenientParsing = $bLenientParsing;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function beStrict() {
|
||||
return $this->withLenientParsing(false);
|
||||
}
|
||||
}
|
||||
40
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/CSSFunction.php
vendored
Normal file
40
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/CSSFunction.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
class CSSFunction extends ValueList {
|
||||
|
||||
protected $sName;
|
||||
|
||||
public function __construct($sName, $aArguments, $sSeparator = ',', $iLineNo = 0) {
|
||||
if($aArguments instanceof RuleValueList) {
|
||||
$sSeparator = $aArguments->getListSeparator();
|
||||
$aArguments = $aArguments->getListComponents();
|
||||
}
|
||||
$this->sName = $sName;
|
||||
$this->iLineNo = $iLineNo;
|
||||
parent::__construct($aArguments, $sSeparator, $iLineNo);
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return $this->sName;
|
||||
}
|
||||
|
||||
public function setName($sName) {
|
||||
$this->sName = $sName;
|
||||
}
|
||||
|
||||
public function getArguments() {
|
||||
return $this->aComponents;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$aArguments = parent::render($oOutputFormat);
|
||||
return "{$this->sName}({$aArguments})";
|
||||
}
|
||||
|
||||
}
|
||||
66
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/CSSString.php
vendored
Normal file
66
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/CSSString.php
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\SourceException;
|
||||
|
||||
class CSSString extends PrimitiveValue {
|
||||
|
||||
private $sString;
|
||||
|
||||
public function __construct($sString, $iLineNo = 0) {
|
||||
$this->sString = $sString;
|
||||
parent::__construct($iLineNo);
|
||||
}
|
||||
|
||||
public static function parse(ParserState $oParserState) {
|
||||
$sBegin = $oParserState->peek();
|
||||
$sQuote = null;
|
||||
if ($sBegin === "'") {
|
||||
$sQuote = "'";
|
||||
} else if ($sBegin === '"') {
|
||||
$sQuote = '"';
|
||||
}
|
||||
if ($sQuote !== null) {
|
||||
$oParserState->consume($sQuote);
|
||||
}
|
||||
$sResult = "";
|
||||
$sContent = null;
|
||||
if ($sQuote === null) {
|
||||
// Unquoted strings end in whitespace or with braces, brackets, parentheses
|
||||
while (!preg_match('/[\\s{}()<>\\[\\]]/isu', $oParserState->peek())) {
|
||||
$sResult .= $oParserState->parseCharacter(false);
|
||||
}
|
||||
} else {
|
||||
while (!$oParserState->comes($sQuote)) {
|
||||
$sContent = $oParserState->parseCharacter(false);
|
||||
if ($sContent === null) {
|
||||
throw new SourceException("Non-well-formed quoted string {$oParserState->peek(3)}", $oParserState->currentLine());
|
||||
}
|
||||
$sResult .= $sContent;
|
||||
}
|
||||
$oParserState->consume($sQuote);
|
||||
}
|
||||
return new CSSString($sResult, $oParserState->currentLine());
|
||||
}
|
||||
|
||||
public function setString($sString) {
|
||||
$this->sString = $sString;
|
||||
}
|
||||
|
||||
public function getString() {
|
||||
return $this->sString;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$sString = addslashes($this->sString);
|
||||
$sString = str_replace("\n", '\A', $sString);
|
||||
return $oOutputFormat->getStringQuotingType() . $sString . $oOutputFormat->getStringQuotingType();
|
||||
}
|
||||
|
||||
}
|
||||
62
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/CalcFunction.php
vendored
Normal file
62
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/CalcFunction.php
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
|
||||
|
||||
class CalcFunction extends CSSFunction {
|
||||
const T_OPERAND = 1;
|
||||
const T_OPERATOR = 2;
|
||||
|
||||
public static function parse(ParserState $oParserState) {
|
||||
$aOperators = array('+', '-', '*', '/');
|
||||
$sFunction = trim($oParserState->consumeUntil('(', false, true));
|
||||
$oCalcList = new CalcRuleValueList($oParserState->currentLine());
|
||||
$oList = new RuleValueList(',', $oParserState->currentLine());
|
||||
$iNestingLevel = 0;
|
||||
$iLastComponentType = NULL;
|
||||
while(!$oParserState->comes(')') || $iNestingLevel > 0) {
|
||||
$oParserState->consumeWhiteSpace();
|
||||
if ($oParserState->comes('(')) {
|
||||
$iNestingLevel++;
|
||||
$oCalcList->addListComponent($oParserState->consume(1));
|
||||
continue;
|
||||
} else if ($oParserState->comes(')')) {
|
||||
$iNestingLevel--;
|
||||
$oCalcList->addListComponent($oParserState->consume(1));
|
||||
continue;
|
||||
}
|
||||
if ($iLastComponentType != CalcFunction::T_OPERAND) {
|
||||
$oVal = Value::parsePrimitiveValue($oParserState);
|
||||
$oCalcList->addListComponent($oVal);
|
||||
$iLastComponentType = CalcFunction::T_OPERAND;
|
||||
} else {
|
||||
if (in_array($oParserState->peek(), $aOperators)) {
|
||||
if (($oParserState->comes('-') || $oParserState->comes('+'))) {
|
||||
if ($oParserState->peek(1, -1) != ' ' || !($oParserState->comes('- ') || $oParserState->comes('+ '))) {
|
||||
throw new UnexpectedTokenException(" {$oParserState->peek()} ", $oParserState->peek(1, -1) . $oParserState->peek(2), 'literal', $oParserState->currentLine());
|
||||
}
|
||||
}
|
||||
$oCalcList->addListComponent($oParserState->consume(1));
|
||||
$iLastComponentType = CalcFunction::T_OPERATOR;
|
||||
} else {
|
||||
throw new UnexpectedTokenException(
|
||||
sprintf(
|
||||
'Next token was expected to be an operand of type %s. Instead "%s" was found.',
|
||||
implode(', ', $aOperators),
|
||||
$oVal
|
||||
),
|
||||
'',
|
||||
'custom',
|
||||
$oParserState->currentLine()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
$oList->addListComponent($oCalcList);
|
||||
$oParserState->consume(')');
|
||||
return new CalcFunction($sFunction, $oList, ',', $oParserState->currentLine());
|
||||
}
|
||||
|
||||
}
|
||||
14
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/CalcRuleValueList.php
vendored
Normal file
14
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/CalcRuleValueList.php
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
class CalcRuleValueList extends RuleValueList {
|
||||
public function __construct($iLineNo = 0) {
|
||||
parent::__construct(array(), ',', $iLineNo);
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
return $oOutputFormat->implode(' ', $this->aComponents);
|
||||
}
|
||||
|
||||
}
|
||||
95
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/Color.php
vendored
Normal file
95
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/Color.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
|
||||
class Color extends CSSFunction {
|
||||
|
||||
public function __construct($aColor, $iLineNo = 0) {
|
||||
parent::__construct(implode('', array_keys($aColor)), $aColor, ',', $iLineNo);
|
||||
}
|
||||
|
||||
public static function parse(ParserState $oParserState) {
|
||||
$aColor = array();
|
||||
if ($oParserState->comes('#')) {
|
||||
$oParserState->consume('#');
|
||||
$sValue = $oParserState->parseIdentifier(false);
|
||||
if ($oParserState->strlen($sValue) === 3) {
|
||||
$sValue = $sValue[0] . $sValue[0] . $sValue[1] . $sValue[1] . $sValue[2] . $sValue[2];
|
||||
} else if ($oParserState->strlen($sValue) === 4) {
|
||||
$sValue = $sValue[0] . $sValue[0] . $sValue[1] . $sValue[1] . $sValue[2] . $sValue[2] . $sValue[3] . $sValue[3];
|
||||
}
|
||||
|
||||
if ($oParserState->strlen($sValue) === 8) {
|
||||
$aColor = array(
|
||||
'r' => new Size(intval($sValue[0] . $sValue[1], 16), null, true, $oParserState->currentLine()),
|
||||
'g' => new Size(intval($sValue[2] . $sValue[3], 16), null, true, $oParserState->currentLine()),
|
||||
'b' => new Size(intval($sValue[4] . $sValue[5], 16), null, true, $oParserState->currentLine()),
|
||||
'a' => new Size(round(self::mapRange(intval($sValue[6] . $sValue[7], 16), 0, 255, 0, 1), 2), null, true, $oParserState->currentLine())
|
||||
);
|
||||
} else {
|
||||
$aColor = array(
|
||||
'r' => new Size(intval($sValue[0] . $sValue[1], 16), null, true, $oParserState->currentLine()),
|
||||
'g' => new Size(intval($sValue[2] . $sValue[3], 16), null, true, $oParserState->currentLine()),
|
||||
'b' => new Size(intval($sValue[4] . $sValue[5], 16), null, true, $oParserState->currentLine())
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$sColorMode = $oParserState->parseIdentifier(true);
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$oParserState->consume('(');
|
||||
$iLength = $oParserState->strlen($sColorMode);
|
||||
for ($i = 0; $i < $iLength; ++$i) {
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$aColor[$sColorMode[$i]] = Size::parse($oParserState, true);
|
||||
$oParserState->consumeWhiteSpace();
|
||||
if ($i < ($iLength - 1)) {
|
||||
$oParserState->consume(',');
|
||||
}
|
||||
}
|
||||
$oParserState->consume(')');
|
||||
}
|
||||
return new Color($aColor, $oParserState->currentLine());
|
||||
}
|
||||
|
||||
private static function mapRange($fVal, $fFromMin, $fFromMax, $fToMin, $fToMax) {
|
||||
$fFromRange = $fFromMax - $fFromMin;
|
||||
$fToRange = $fToMax - $fToMin;
|
||||
$fMultiplier = $fToRange / $fFromRange;
|
||||
$fNewVal = $fVal - $fFromMin;
|
||||
$fNewVal *= $fMultiplier;
|
||||
return $fNewVal + $fToMin;
|
||||
}
|
||||
|
||||
public function getColor() {
|
||||
return $this->aComponents;
|
||||
}
|
||||
|
||||
public function setColor($aColor) {
|
||||
$this->setName(implode('', array_keys($aColor)));
|
||||
$this->aComponents = $aColor;
|
||||
}
|
||||
|
||||
public function getColorDescription() {
|
||||
return $this->getName();
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
// Shorthand RGB color values
|
||||
if($oOutputFormat->getRGBHashNotation() && implode('', array_keys($this->aComponents)) === 'rgb') {
|
||||
$sResult = sprintf(
|
||||
'%02x%02x%02x',
|
||||
$this->aComponents['r']->getSize(),
|
||||
$this->aComponents['g']->getSize(),
|
||||
$this->aComponents['b']->getSize()
|
||||
);
|
||||
return '#'.(($sResult[0] == $sResult[1]) && ($sResult[2] == $sResult[3]) && ($sResult[4] == $sResult[5]) ? "$sResult[0]$sResult[2]$sResult[4]" : $sResult);
|
||||
}
|
||||
return parent::render($oOutputFormat);
|
||||
}
|
||||
}
|
||||
41
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/LineName.php
vendored
Normal file
41
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/LineName.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
|
||||
|
||||
class LineName extends ValueList {
|
||||
public function __construct($aComponents = array(), $iLineNo = 0) {
|
||||
parent::__construct($aComponents, ' ', $iLineNo);
|
||||
}
|
||||
|
||||
public static function parse(ParserState $oParserState) {
|
||||
$oParserState->consume('[');
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$aNames = array();
|
||||
do {
|
||||
if($oParserState->getSettings()->bLenientParsing) {
|
||||
try {
|
||||
$aNames[] = $oParserState->parseIdentifier();
|
||||
} catch(UnexpectedTokenException $e) {}
|
||||
} else {
|
||||
$aNames[] = $oParserState->parseIdentifier();
|
||||
}
|
||||
$oParserState->consumeWhiteSpace();
|
||||
} while (!$oParserState->comes(']'));
|
||||
$oParserState->consume(']');
|
||||
return new LineName($aNames, $oParserState->currentLine());
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
return '[' . parent::render(\Sabberworm\CSS\OutputFormat::createCompact()) . ']';
|
||||
}
|
||||
|
||||
}
|
||||
10
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/PrimitiveValue.php
vendored
Normal file
10
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/PrimitiveValue.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
abstract class PrimitiveValue extends Value {
|
||||
public function __construct($iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
}
|
||||
|
||||
}
|
||||
9
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/RuleValueList.php
vendored
Normal file
9
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/RuleValueList.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
class RuleValueList extends ValueList {
|
||||
public function __construct($sSeparator = ',', $iLineNo = 0) {
|
||||
parent::__construct(array(), $sSeparator, $iLineNo);
|
||||
}
|
||||
}
|
||||
122
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/Size.php
vendored
Normal file
122
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/Size.php
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
|
||||
class Size extends PrimitiveValue {
|
||||
|
||||
const ABSOLUTE_SIZE_UNITS = 'px/cm/mm/mozmm/in/pt/pc/vh/vw/vm/vmin/vmax/rem'; //vh/vw/vm(ax)/vmin/rem are absolute insofar as they don’t scale to the immediate parent (only the viewport)
|
||||
const RELATIVE_SIZE_UNITS = '%/em/ex/ch/fr';
|
||||
const NON_SIZE_UNITS = 'deg/grad/rad/s/ms/turns/Hz/kHz';
|
||||
|
||||
private static $SIZE_UNITS = null;
|
||||
|
||||
private $fSize;
|
||||
private $sUnit;
|
||||
private $bIsColorComponent;
|
||||
|
||||
public function __construct($fSize, $sUnit = null, $bIsColorComponent = false, $iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
$this->fSize = floatval($fSize);
|
||||
$this->sUnit = $sUnit;
|
||||
$this->bIsColorComponent = $bIsColorComponent;
|
||||
}
|
||||
|
||||
public static function parse(ParserState $oParserState, $bIsColorComponent = false) {
|
||||
$sSize = '';
|
||||
if ($oParserState->comes('-')) {
|
||||
$sSize .= $oParserState->consume('-');
|
||||
}
|
||||
while (is_numeric($oParserState->peek()) || $oParserState->comes('.')) {
|
||||
if ($oParserState->comes('.')) {
|
||||
$sSize .= $oParserState->consume('.');
|
||||
} else {
|
||||
$sSize .= $oParserState->consume(1);
|
||||
}
|
||||
}
|
||||
|
||||
$sUnit = null;
|
||||
$aSizeUnits = self::getSizeUnits();
|
||||
foreach($aSizeUnits as $iLength => &$aValues) {
|
||||
$sKey = strtolower($oParserState->peek($iLength));
|
||||
if(array_key_exists($sKey, $aValues)) {
|
||||
if (($sUnit = $aValues[$sKey]) !== null) {
|
||||
$oParserState->consume($iLength);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Size(floatval($sSize), $sUnit, $bIsColorComponent, $oParserState->currentLine());
|
||||
}
|
||||
|
||||
private static function getSizeUnits() {
|
||||
if(self::$SIZE_UNITS === null) {
|
||||
self::$SIZE_UNITS = array();
|
||||
foreach (explode('/', Size::ABSOLUTE_SIZE_UNITS.'/'.Size::RELATIVE_SIZE_UNITS.'/'.Size::NON_SIZE_UNITS) as $val) {
|
||||
$iSize = strlen($val);
|
||||
if(!isset(self::$SIZE_UNITS[$iSize])) {
|
||||
self::$SIZE_UNITS[$iSize] = array();
|
||||
}
|
||||
self::$SIZE_UNITS[$iSize][strtolower($val)] = $val;
|
||||
}
|
||||
|
||||
// FIXME: Should we not order the longest units first?
|
||||
ksort(self::$SIZE_UNITS, SORT_NUMERIC);
|
||||
}
|
||||
|
||||
return self::$SIZE_UNITS;
|
||||
}
|
||||
|
||||
public function setUnit($sUnit) {
|
||||
$this->sUnit = $sUnit;
|
||||
}
|
||||
|
||||
public function getUnit() {
|
||||
return $this->sUnit;
|
||||
}
|
||||
|
||||
public function setSize($fSize) {
|
||||
$this->fSize = floatval($fSize);
|
||||
}
|
||||
|
||||
public function getSize() {
|
||||
return $this->fSize;
|
||||
}
|
||||
|
||||
public function isColorComponent() {
|
||||
return $this->bIsColorComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the number stored in this Size really represents a size (as in a length of something on screen).
|
||||
* @return false if the unit an angle, a duration, a frequency or the number is a component in a Color object.
|
||||
*/
|
||||
public function isSize() {
|
||||
if (in_array($this->sUnit, explode('/', self::NON_SIZE_UNITS))) {
|
||||
return false;
|
||||
}
|
||||
return !$this->isColorComponent();
|
||||
}
|
||||
|
||||
public function isRelative() {
|
||||
if (in_array($this->sUnit, explode('/', self::RELATIVE_SIZE_UNITS))) {
|
||||
return true;
|
||||
}
|
||||
if ($this->sUnit === null && $this->fSize != 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
$l = localeconv();
|
||||
$sPoint = preg_quote($l['decimal_point'], '/');
|
||||
return preg_replace(array("/$sPoint/", "/^(-?)0\./"), array('.', '$1.'), $this->fSize) . ($this->sUnit === null ? '' : $this->sUnit);
|
||||
}
|
||||
|
||||
}
|
||||
49
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/URL.php
vendored
Normal file
49
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/URL.php
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
|
||||
class URL extends PrimitiveValue {
|
||||
|
||||
private $oURL;
|
||||
|
||||
public function __construct(CSSString $oURL, $iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
$this->oURL = $oURL;
|
||||
}
|
||||
|
||||
public static function parse(ParserState $oParserState) {
|
||||
$bUseUrl = $oParserState->comes('url', true);
|
||||
if ($bUseUrl) {
|
||||
$oParserState->consume('url');
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$oParserState->consume('(');
|
||||
}
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$oResult = new URL(CSSString::parse($oParserState), $oParserState->currentLine());
|
||||
if ($bUseUrl) {
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$oParserState->consume(')');
|
||||
}
|
||||
return $oResult;
|
||||
}
|
||||
|
||||
|
||||
public function setURL(CSSString $oURL) {
|
||||
$this->oURL = $oURL;
|
||||
}
|
||||
|
||||
public function getURL() {
|
||||
return $this->oURL;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
return "url({$this->oURL->render($oOutputFormat)})";
|
||||
}
|
||||
|
||||
}
|
||||
131
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/Value.php
vendored
Normal file
131
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/Value.php
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
use Sabberworm\CSS\Parsing\ParserState;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
|
||||
use Sabberworm\CSS\Renderable;
|
||||
|
||||
abstract class Value implements Renderable {
|
||||
protected $iLineNo;
|
||||
|
||||
public function __construct($iLineNo = 0) {
|
||||
$this->iLineNo = $iLineNo;
|
||||
}
|
||||
|
||||
public static function parseValue(ParserState $oParserState, $aListDelimiters = array()) {
|
||||
$aStack = array();
|
||||
$oParserState->consumeWhiteSpace();
|
||||
//Build a list of delimiters and parsed values
|
||||
while (!($oParserState->comes('}') || $oParserState->comes(';') || $oParserState->comes('!') || $oParserState->comes(')') || $oParserState->comes('\\'))) {
|
||||
if (count($aStack) > 0) {
|
||||
$bFoundDelimiter = false;
|
||||
foreach ($aListDelimiters as $sDelimiter) {
|
||||
if ($oParserState->comes($sDelimiter)) {
|
||||
array_push($aStack, $oParserState->consume($sDelimiter));
|
||||
$oParserState->consumeWhiteSpace();
|
||||
$bFoundDelimiter = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$bFoundDelimiter) {
|
||||
//Whitespace was the list delimiter
|
||||
array_push($aStack, ' ');
|
||||
}
|
||||
}
|
||||
array_push($aStack, self::parsePrimitiveValue($oParserState));
|
||||
$oParserState->consumeWhiteSpace();
|
||||
}
|
||||
//Convert the list to list objects
|
||||
foreach ($aListDelimiters as $sDelimiter) {
|
||||
if (count($aStack) === 1) {
|
||||
return $aStack[0];
|
||||
}
|
||||
$iStartPosition = null;
|
||||
while (($iStartPosition = array_search($sDelimiter, $aStack, true)) !== false) {
|
||||
$iLength = 2; //Number of elements to be joined
|
||||
for ($i = $iStartPosition + 2; $i < count($aStack); $i+=2, ++$iLength) {
|
||||
if ($sDelimiter !== $aStack[$i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
$oList = new RuleValueList($sDelimiter, $oParserState->currentLine());
|
||||
for ($i = $iStartPosition - 1; $i - $iStartPosition + 1 < $iLength * 2; $i+=2) {
|
||||
$oList->addListComponent($aStack[$i]);
|
||||
}
|
||||
array_splice($aStack, $iStartPosition - 1, $iLength * 2 - 1, array($oList));
|
||||
}
|
||||
}
|
||||
if (!isset($aStack[0])) {
|
||||
throw new UnexpectedTokenException(" {$oParserState->peek()} ", $oParserState->peek(1, -1) . $oParserState->peek(2), 'literal', $oParserState->currentLine());
|
||||
}
|
||||
return $aStack[0];
|
||||
}
|
||||
|
||||
public static function parseIdentifierOrFunction(ParserState $oParserState, $bIgnoreCase = false) {
|
||||
$sResult = $oParserState->parseIdentifier($bIgnoreCase);
|
||||
|
||||
if ($oParserState->comes('(')) {
|
||||
$oParserState->consume('(');
|
||||
$aArguments = Value::parseValue($oParserState, array('=', ' ', ','));
|
||||
$sResult = new CSSFunction($sResult, $aArguments, ',', $oParserState->currentLine());
|
||||
$oParserState->consume(')');
|
||||
}
|
||||
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
public static function parsePrimitiveValue(ParserState $oParserState) {
|
||||
$oValue = null;
|
||||
$oParserState->consumeWhiteSpace();
|
||||
if (is_numeric($oParserState->peek()) || ($oParserState->comes('-.') && is_numeric($oParserState->peek(1, 2))) || (($oParserState->comes('-') || $oParserState->comes('.')) && is_numeric($oParserState->peek(1, 1)))) {
|
||||
$oValue = Size::parse($oParserState);
|
||||
} else if ($oParserState->comes('#') || $oParserState->comes('rgb', true) || $oParserState->comes('hsl', true)) {
|
||||
$oValue = Color::parse($oParserState);
|
||||
} else if ($oParserState->comes('url', true)) {
|
||||
$oValue = URL::parse($oParserState);
|
||||
} else if ($oParserState->comes('calc', true) || $oParserState->comes('-webkit-calc', true) || $oParserState->comes('-moz-calc', true)) {
|
||||
$oValue = CalcFunction::parse($oParserState);
|
||||
} else if ($oParserState->comes("'") || $oParserState->comes('"')) {
|
||||
$oValue = CSSString::parse($oParserState);
|
||||
} else if ($oParserState->comes("progid:") && $oParserState->getSettings()->bLenientParsing) {
|
||||
$oValue = self::parseMicrosoftFilter($oParserState);
|
||||
} else if ($oParserState->comes("[")) {
|
||||
$oValue = LineName::parse($oParserState);
|
||||
} else if ($oParserState->comes("U+")) {
|
||||
$oValue = self::parseUnicodeRangeValue($oParserState);
|
||||
} else {
|
||||
$oValue = self::parseIdentifierOrFunction($oParserState);
|
||||
}
|
||||
$oParserState->consumeWhiteSpace();
|
||||
return $oValue;
|
||||
}
|
||||
|
||||
private static function parseMicrosoftFilter(ParserState $oParserState) {
|
||||
$sFunction = $oParserState->consumeUntil('(', false, true);
|
||||
$aArguments = Value::parseValue($oParserState, array(',', '='));
|
||||
return new CSSFunction($sFunction, $aArguments, ',', $oParserState->currentLine());
|
||||
}
|
||||
|
||||
private static function parseUnicodeRangeValue(ParserState $oParserState) {
|
||||
$iCodepointMaxLenth = 6; // Code points outside BMP can use up to six digits
|
||||
$sRange = "";
|
||||
$oParserState->consume("U+");
|
||||
do {
|
||||
if ($oParserState->comes('-')) $iCodepointMaxLenth = 13; // Max length is 2 six digit code points + the dash(-) between them
|
||||
$sRange .= $oParserState->consume(1);
|
||||
} while (strlen($sRange) < $iCodepointMaxLenth && preg_match("/[A-Fa-f0-9\?-]/", $oParserState->peek()));
|
||||
return "U+{$sRange}";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLineNo() {
|
||||
return $this->iLineNo;
|
||||
}
|
||||
|
||||
//Methods are commented out because re-declaring them here is a fatal error in PHP < 5.3.9
|
||||
//public abstract function __toString();
|
||||
//public abstract function render(\Sabberworm\CSS\OutputFormat $oOutputFormat);
|
||||
}
|
||||
47
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/ValueList.php
vendored
Normal file
47
vendor/sabberworm/php-css-parser/lib/Sabberworm/CSS/Value/ValueList.php
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\Value;
|
||||
|
||||
abstract class ValueList extends Value {
|
||||
|
||||
protected $aComponents;
|
||||
protected $sSeparator;
|
||||
|
||||
public function __construct($aComponents = array(), $sSeparator = ',', $iLineNo = 0) {
|
||||
parent::__construct($iLineNo);
|
||||
if (!is_array($aComponents)) {
|
||||
$aComponents = array($aComponents);
|
||||
}
|
||||
$this->aComponents = $aComponents;
|
||||
$this->sSeparator = $sSeparator;
|
||||
}
|
||||
|
||||
public function addListComponent($mComponent) {
|
||||
$this->aComponents[] = $mComponent;
|
||||
}
|
||||
|
||||
public function getListComponents() {
|
||||
return $this->aComponents;
|
||||
}
|
||||
|
||||
public function setListComponents($aComponents) {
|
||||
$this->aComponents = $aComponents;
|
||||
}
|
||||
|
||||
public function getListSeparator() {
|
||||
return $this->sSeparator;
|
||||
}
|
||||
|
||||
public function setListSeparator($sSeparator) {
|
||||
$this->sSeparator = $sSeparator;
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return $this->render(new \Sabberworm\CSS\OutputFormat());
|
||||
}
|
||||
|
||||
public function render(\Sabberworm\CSS\OutputFormat $oOutputFormat) {
|
||||
return $oOutputFormat->implode($oOutputFormat->spaceBeforeListArgumentSeparator($this->sSeparator) . $this->sSeparator . $oOutputFormat->spaceAfterListArgumentSeparator($this->sSeparator), $this->aComponents);
|
||||
}
|
||||
|
||||
}
|
||||
10
vendor/sabberworm/php-css-parser/phpunit.xml
vendored
Normal file
10
vendor/sabberworm/php-css-parser/phpunit.xml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.5/phpunit.xsd"
|
||||
bootstrap="tests/bootstrap.php">
|
||||
<testsuites>
|
||||
<testsuite name="Project Test Suite">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
27
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/CSSList/AtRuleBlockListTest.php
vendored
Normal file
27
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/CSSList/AtRuleBlockListTest.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\Parser;
|
||||
|
||||
class AtRuleBlockListTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testMediaQueries() {
|
||||
$sCss = '@media(min-width: 768px){.class{color:red}}';
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
$aContents = $oDoc->getContents();
|
||||
$oMediaQuery = $aContents[0];
|
||||
$this->assertSame('media', $oMediaQuery->atRuleName(), 'Does not interpret the type as a function');
|
||||
$this->assertSame('(min-width: 768px)', $oMediaQuery->atRuleArgs(), 'The media query is the value');
|
||||
|
||||
$sCss = '@media (min-width: 768px) {.class{color:red}}';
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
$aContents = $oDoc->getContents();
|
||||
$oMediaQuery = $aContents[0];
|
||||
$this->assertSame('media', $oMediaQuery->atRuleName(), 'Does not interpret the type as a function');
|
||||
$this->assertSame('(min-width: 768px)', $oMediaQuery->atRuleArgs(), 'The media query is the value');
|
||||
}
|
||||
|
||||
}
|
||||
26
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/CSSList/DocumentTest.php
vendored
Normal file
26
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/CSSList/DocumentTest.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\CSSList;
|
||||
|
||||
use Sabberworm\CSS\Parser;
|
||||
|
||||
class DocumentTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
public function testOverrideContents() {
|
||||
$sCss = '.thing { left: 10px; }';
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
$aContents = $oDoc->getContents();
|
||||
$this->assertCount(1, $aContents);
|
||||
|
||||
$sCss2 = '.otherthing { right: 10px; }';
|
||||
$oParser2 = new Parser($sCss);
|
||||
$oDoc2 = $oParser2->parse();
|
||||
$aContents2 = $oDoc2->getContents();
|
||||
|
||||
$oDoc->setContents(array($aContents[0], $aContents2[0]));
|
||||
$aFinalContents = $oDoc->getContents();
|
||||
$this->assertCount(2, $aFinalContents);
|
||||
}
|
||||
|
||||
}
|
||||
170
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/OutputFormatTest.php
vendored
Normal file
170
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/OutputFormatTest.php
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS;
|
||||
|
||||
use Sabberworm\CSS\Parser;
|
||||
use Sabberworm\CSS\OutputFormat;
|
||||
|
||||
global $TEST_CSS;
|
||||
|
||||
$TEST_CSS = <<<EOT
|
||||
|
||||
.main, .test {
|
||||
font: italic normal bold 16px/1.2 "Helvetica", Verdana, sans-serif;
|
||||
background: white;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
.main {
|
||||
background-size: 100% 100%;
|
||||
font-size: 1.3em;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
EOT;
|
||||
|
||||
class OutputFormatTest extends \PHPUnit_Framework_TestCase {
|
||||
private $oParser;
|
||||
private $oDocument;
|
||||
|
||||
function setUp() {
|
||||
global $TEST_CSS;
|
||||
$this->oParser = new Parser($TEST_CSS);
|
||||
$this->oDocument = $this->oParser->parse();
|
||||
}
|
||||
|
||||
public function testPlain() {
|
||||
$this->assertSame('.main, .test {font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white;}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render());
|
||||
}
|
||||
|
||||
public function testCompact() {
|
||||
$this->assertSame('.main,.test{font:italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background:white;}@media screen{.main{background-size:100% 100%;font-size:1.3em;background-color:#fff;}}', $this->oDocument->render(OutputFormat::createCompact()));
|
||||
}
|
||||
|
||||
public function testPretty() {
|
||||
global $TEST_CSS;
|
||||
$this->assertSame($TEST_CSS, $this->oDocument->render(OutputFormat::createPretty()));
|
||||
}
|
||||
|
||||
public function testSpaceAfterListArgumentSeparator() {
|
||||
$this->assertSame('.main, .test {font: italic normal bold 16px/ 1.2 "Helvetica", Verdana, sans-serif;background: white;}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setSpaceAfterListArgumentSeparator(" ")));
|
||||
}
|
||||
|
||||
public function testSpaceAfterListArgumentSeparatorComplex() {
|
||||
$this->assertSame('.main, .test {font: italic normal bold 16px/1.2 "Helvetica", Verdana, sans-serif;background: white;}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setSpaceAfterListArgumentSeparator(array('default' => ' ', ',' => "\t", '/' => '', ' ' => ''))));
|
||||
}
|
||||
|
||||
public function testSpaceAfterSelectorSeparator() {
|
||||
$this->assertSame('.main,
|
||||
.test {font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white;}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setSpaceAfterSelectorSeparator("\n")));
|
||||
}
|
||||
|
||||
public function testStringQuotingType() {
|
||||
$this->assertSame('.main, .test {font: italic normal bold 16px/1.2 \'Helvetica\',Verdana,sans-serif;background: white;}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setStringQuotingType("'")));
|
||||
}
|
||||
|
||||
public function testRGBHashNotation() {
|
||||
$this->assertSame('.main, .test {font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white;}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: rgb(255,255,255);}}', $this->oDocument->render(OutputFormat::create()->setRGBHashNotation(false)));
|
||||
}
|
||||
|
||||
public function testSemicolonAfterLastRule() {
|
||||
$this->assertSame('.main, .test {font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff}}', $this->oDocument->render(OutputFormat::create()->setSemicolonAfterLastRule(false)));
|
||||
}
|
||||
|
||||
public function testSpaceAfterRuleName() {
|
||||
$this->assertSame('.main, .test {font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white;}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setSpaceAfterRuleName("\t")));
|
||||
}
|
||||
|
||||
public function testSpaceRules() {
|
||||
$this->assertSame('.main, .test {
|
||||
font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;
|
||||
background: white;
|
||||
}
|
||||
@media screen {.main {
|
||||
background-size: 100% 100%;
|
||||
font-size: 1.3em;
|
||||
background-color: #fff;
|
||||
}}', $this->oDocument->render(OutputFormat::create()->set('Space*Rules', "\n")));
|
||||
}
|
||||
|
||||
public function testSpaceBlocks() {
|
||||
$this->assertSame('
|
||||
.main, .test {font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white;}
|
||||
@media screen {
|
||||
.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}
|
||||
}
|
||||
', $this->oDocument->render(OutputFormat::create()->set('Space*Blocks', "\n")));
|
||||
}
|
||||
|
||||
public function testSpaceBoth() {
|
||||
$this->assertSame('
|
||||
.main, .test {
|
||||
font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;
|
||||
background: white;
|
||||
}
|
||||
@media screen {
|
||||
.main {
|
||||
background-size: 100% 100%;
|
||||
font-size: 1.3em;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
', $this->oDocument->render(OutputFormat::create()->set('Space*Rules', "\n")->set('Space*Blocks', "\n")));
|
||||
}
|
||||
|
||||
public function testSpaceBetweenBlocks() {
|
||||
$this->assertSame('.main, .test {font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white;}@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setSpaceBetweenBlocks('')));
|
||||
}
|
||||
|
||||
public function testIndentation() {
|
||||
$this->assertSame('
|
||||
.main, .test {
|
||||
font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;
|
||||
background: white;
|
||||
}
|
||||
@media screen {
|
||||
.main {
|
||||
background-size: 100% 100%;
|
||||
font-size: 1.3em;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
', $this->oDocument->render(OutputFormat::create()->set('Space*Rules', "\n")->set('Space*Blocks', "\n")->setIndentation('')));
|
||||
}
|
||||
|
||||
public function testSpaceBeforeBraces() {
|
||||
$this->assertSame('.main, .test{font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white;}
|
||||
@media screen{.main{background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setSpaceBeforeOpeningBrace('')));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\OutputException
|
||||
*/
|
||||
public function testIgnoreExceptionsOff() {
|
||||
$aBlocks = $this->oDocument->getAllDeclarationBlocks();
|
||||
$oFirstBlock = $aBlocks[0];
|
||||
$oFirstBlock->removeSelector('.main');
|
||||
$this->assertSame('.test {font: italic normal bold 16px/1.2 "Helvetica",Verdana,sans-serif;background: white;}
|
||||
@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setIgnoreExceptions(false)));
|
||||
$oFirstBlock->removeSelector('.test');
|
||||
$this->oDocument->render(OutputFormat::create()->setIgnoreExceptions(false));
|
||||
}
|
||||
|
||||
public function testIgnoreExceptionsOn() {
|
||||
$aBlocks = $this->oDocument->getAllDeclarationBlocks();
|
||||
$oFirstBlock = $aBlocks[0];
|
||||
$oFirstBlock->removeSelector('.main');
|
||||
$oFirstBlock->removeSelector('.test');
|
||||
$this->assertSame('@media screen {.main {background-size: 100% 100%;font-size: 1.3em;background-color: #fff;}}', $this->oDocument->render(OutputFormat::create()->setIgnoreExceptions(true)));
|
||||
}
|
||||
|
||||
}
|
||||
714
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/ParserTest.php
vendored
Normal file
714
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/ParserTest.php
vendored
Normal file
@@ -0,0 +1,714 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS;
|
||||
|
||||
use Sabberworm\CSS\CSSList\KeyFrame;
|
||||
use Sabberworm\CSS\Value\Size;
|
||||
use Sabberworm\CSS\Property\Selector;
|
||||
use Sabberworm\CSS\RuleSet\DeclarationBlock;
|
||||
use Sabberworm\CSS\Property\AtRule;
|
||||
use Sabberworm\CSS\Value\URL;
|
||||
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
|
||||
|
||||
class ParserTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
function testFiles() {
|
||||
$sDirectory = dirname(__FILE__) . '/../../files';
|
||||
if ($rHandle = opendir($sDirectory)) {
|
||||
/* This is the correct way to loop over the directory. */
|
||||
while (false !== ($sFileName = readdir($rHandle))) {
|
||||
if (strpos($sFileName, '.') === 0) {
|
||||
continue;
|
||||
}
|
||||
if (strrpos($sFileName, '.css') !== strlen($sFileName) - strlen('.css')) {
|
||||
continue;
|
||||
}
|
||||
if (strpos($sFileName, '-') === 0) {
|
||||
//Either a file which SHOULD fail (at least in strict mode) or a future test of a as-of-now missing feature
|
||||
continue;
|
||||
}
|
||||
$oParser = new Parser(file_get_contents($sDirectory . DIRECTORY_SEPARATOR . $sFileName));
|
||||
try {
|
||||
$this->assertNotEquals('', $oParser->parse()->render());
|
||||
} catch (\Exception $e) {
|
||||
$this->fail($e);
|
||||
}
|
||||
}
|
||||
closedir($rHandle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testFiles
|
||||
*/
|
||||
function testColorParsing() {
|
||||
$oDoc = $this->parsedStructureForFile('colortest');
|
||||
foreach ($oDoc->getAllRuleSets() as $oRuleSet) {
|
||||
if (!$oRuleSet instanceof DeclarationBlock) {
|
||||
continue;
|
||||
}
|
||||
$sSelector = $oRuleSet->getSelectors();
|
||||
$sSelector = $sSelector[0]->getSelector();
|
||||
if ($sSelector === '#mine') {
|
||||
$aColorRule = $oRuleSet->getRules('color');
|
||||
$oColor = $aColorRule[0]->getValue();
|
||||
$this->assertSame('red', $oColor);
|
||||
$aColorRule = $oRuleSet->getRules('background-');
|
||||
$oColor = $aColorRule[0]->getValue();
|
||||
$this->assertEquals(array('r' => new Size(35.0, null, true, $oColor->getLineNo()), 'g' => new Size(35.0, null, true, $oColor->getLineNo()), 'b' => new Size(35.0, null, true, $oColor->getLineNo())), $oColor->getColor());
|
||||
$aColorRule = $oRuleSet->getRules('border-color');
|
||||
$oColor = $aColorRule[0]->getValue();
|
||||
$this->assertEquals(array('r' => new Size(10.0, null, true, $oColor->getLineNo()), 'g' => new Size(100.0, null, true, $oColor->getLineNo()), 'b' => new Size(230.0, null, true, $oColor->getLineNo())), $oColor->getColor());
|
||||
$oColor = $aColorRule[1]->getValue();
|
||||
$this->assertEquals(array('r' => new Size(10.0, null, true, $oColor->getLineNo()), 'g' => new Size(100.0, null, true, $oColor->getLineNo()), 'b' => new Size(231.0, null, true, $oColor->getLineNo()), 'a' => new Size("0000.3", null, true, $oColor->getLineNo())), $oColor->getColor());
|
||||
$aColorRule = $oRuleSet->getRules('outline-color');
|
||||
$oColor = $aColorRule[0]->getValue();
|
||||
$this->assertEquals(array('r' => new Size(34.0, null, true, $oColor->getLineNo()), 'g' => new Size(34.0, null, true, $oColor->getLineNo()), 'b' => new Size(34.0, null, true, $oColor->getLineNo())), $oColor->getColor());
|
||||
} else if($sSelector === '#yours') {
|
||||
$aColorRule = $oRuleSet->getRules('background-color');
|
||||
$oColor = $aColorRule[0]->getValue();
|
||||
$this->assertEquals(array('h' => new Size(220.0, null, true, $oColor->getLineNo()), 's' => new Size(10.0, '%', true, $oColor->getLineNo()), 'l' => new Size(220.0, '%', true, $oColor->getLineNo())), $oColor->getColor());
|
||||
$oColor = $aColorRule[1]->getValue();
|
||||
$this->assertEquals(array('h' => new Size(220.0, null, true, $oColor->getLineNo()), 's' => new Size(10.0, '%', true, $oColor->getLineNo()), 'l' => new Size(220.0, '%', true, $oColor->getLineNo()), 'a' => new Size(0000.3, null, true, $oColor->getLineNo())), $oColor->getColor());
|
||||
}
|
||||
}
|
||||
foreach ($oDoc->getAllValues('color') as $sColor) {
|
||||
$this->assertSame('red', $sColor);
|
||||
}
|
||||
$this->assertSame('#mine {color: red;border-color: #0a64e6;border-color: rgba(10,100,231,.3);outline-color: #222;background-color: #232323;}
|
||||
#yours {background-color: hsl(220,10%,220%);background-color: hsla(220,10%,220%,.3);}', $oDoc->render());
|
||||
}
|
||||
|
||||
function testUnicodeParsing() {
|
||||
$oDoc = $this->parsedStructureForFile('unicode');
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oRuleSet) {
|
||||
$sSelector = $oRuleSet->getSelectors();
|
||||
$sSelector = $sSelector[0]->getSelector();
|
||||
if (substr($sSelector, 0, strlen('.test-')) !== '.test-') {
|
||||
continue;
|
||||
}
|
||||
$aContentRules = $oRuleSet->getRules('content');
|
||||
$aContents = $aContentRules[0]->getValues();
|
||||
$sString = $aContents[0][0]->__toString();
|
||||
if ($sSelector == '.test-1') {
|
||||
$this->assertSame('" "', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-2') {
|
||||
$this->assertSame('"é"', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-3') {
|
||||
$this->assertSame('" "', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-4') {
|
||||
$this->assertSame('"𝄞"', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-5') {
|
||||
$this->assertSame('"水"', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-6') {
|
||||
$this->assertSame('"¥"', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-7') {
|
||||
$this->assertSame('"\A"', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-8') {
|
||||
$this->assertSame('"\"\""', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-9') {
|
||||
$this->assertSame('"\"\\\'"', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-10') {
|
||||
$this->assertSame('"\\\'\\\\"', $sString);
|
||||
}
|
||||
if ($sSelector == '.test-11') {
|
||||
$this->assertSame('"test"', $sString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testUnicodeRangeParsing() {
|
||||
$oDoc = $this->parsedStructureForFile('unicode-range');
|
||||
$sExpected = "@font-face {unicode-range: U+0100-024F,U+0259,U+1E??-2EFF,U+202F;}";
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testSpecificity() {
|
||||
$oDoc = $this->parsedStructureForFile('specificity');
|
||||
$oDeclarationBlock = $oDoc->getAllDeclarationBlocks();
|
||||
$oDeclarationBlock = $oDeclarationBlock[0];
|
||||
$aSelectors = $oDeclarationBlock->getSelectors();
|
||||
foreach ($aSelectors as $oSelector) {
|
||||
switch ($oSelector->getSelector()) {
|
||||
case "#test .help":
|
||||
$this->assertSame(110, $oSelector->getSpecificity());
|
||||
break;
|
||||
case "#file":
|
||||
$this->assertSame(100, $oSelector->getSpecificity());
|
||||
break;
|
||||
case ".help:hover":
|
||||
$this->assertSame(20, $oSelector->getSpecificity());
|
||||
break;
|
||||
case "ol li::before":
|
||||
$this->assertSame(3, $oSelector->getSpecificity());
|
||||
break;
|
||||
case "li.green":
|
||||
$this->assertSame(11, $oSelector->getSpecificity());
|
||||
break;
|
||||
default:
|
||||
$this->fail("specificity: untested selector " . $oSelector->getSelector());
|
||||
}
|
||||
}
|
||||
$this->assertEquals(array(new Selector('#test .help', true)), $oDoc->getSelectorsBySpecificity('> 100'));
|
||||
$this->assertEquals(array(new Selector('#test .help', true), new Selector('#file', true)), $oDoc->getSelectorsBySpecificity('>= 100'));
|
||||
$this->assertEquals(array(new Selector('#file', true)), $oDoc->getSelectorsBySpecificity('=== 100'));
|
||||
$this->assertEquals(array(new Selector('#file', true)), $oDoc->getSelectorsBySpecificity('== 100'));
|
||||
$this->assertEquals(array(new Selector('#file', true), new Selector('.help:hover', true), new Selector('li.green', true), new Selector('ol li::before', true)), $oDoc->getSelectorsBySpecificity('<= 100'));
|
||||
$this->assertEquals(array(new Selector('.help:hover', true), new Selector('li.green', true), new Selector('ol li::before', true)), $oDoc->getSelectorsBySpecificity('< 100'));
|
||||
$this->assertEquals(array(new Selector('li.green', true)), $oDoc->getSelectorsBySpecificity('11'));
|
||||
$this->assertEquals(array(new Selector('ol li::before', true)), $oDoc->getSelectorsBySpecificity(3));
|
||||
}
|
||||
|
||||
function testManipulation() {
|
||||
$oDoc = $this->parsedStructureForFile('atrules');
|
||||
$this->assertSame('@charset "utf-8";
|
||||
@font-face {font-family: "CrassRoots";src: url("../media/cr.ttf");}
|
||||
html, body {font-size: -.6em;}
|
||||
@keyframes mymove {from {top: 0px;}
|
||||
to {top: 200px;}}
|
||||
@-moz-keyframes some-move {from {top: 0px;}
|
||||
to {top: 200px;}}
|
||||
@supports ( (perspective: 10px) or (-moz-perspective: 10px) or (-webkit-perspective: 10px) or (-ms-perspective: 10px) or (-o-perspective: 10px) ) {body {font-family: "Helvetica";}}
|
||||
@page :pseudo-class {margin: 2in;}
|
||||
@-moz-document url(http://www.w3.org/),
|
||||
url-prefix(http://www.w3.org/Style/),
|
||||
domain(mozilla.org),
|
||||
regexp("https:.*") {body {color: purple;background: yellow;}}
|
||||
@media screen and (orientation: landscape) {@-ms-viewport {width: 1024px;height: 768px;}}
|
||||
@region-style #intro {p {color: blue;}}', $oDoc->render());
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oBlock) {
|
||||
foreach ($oBlock->getSelectors() as $oSelector) {
|
||||
//Loop over all selector parts (the comma-separated strings in a selector) and prepend the id
|
||||
$oSelector->setSelector('#my_id ' . $oSelector->getSelector());
|
||||
}
|
||||
}
|
||||
$this->assertSame('@charset "utf-8";
|
||||
@font-face {font-family: "CrassRoots";src: url("../media/cr.ttf");}
|
||||
#my_id html, #my_id body {font-size: -.6em;}
|
||||
@keyframes mymove {from {top: 0px;}
|
||||
to {top: 200px;}}
|
||||
@-moz-keyframes some-move {from {top: 0px;}
|
||||
to {top: 200px;}}
|
||||
@supports ( (perspective: 10px) or (-moz-perspective: 10px) or (-webkit-perspective: 10px) or (-ms-perspective: 10px) or (-o-perspective: 10px) ) {#my_id body {font-family: "Helvetica";}}
|
||||
@page :pseudo-class {margin: 2in;}
|
||||
@-moz-document url(http://www.w3.org/),
|
||||
url-prefix(http://www.w3.org/Style/),
|
||||
domain(mozilla.org),
|
||||
regexp("https:.*") {#my_id body {color: purple;background: yellow;}}
|
||||
@media screen and (orientation: landscape) {@-ms-viewport {width: 1024px;height: 768px;}}
|
||||
@region-style #intro {#my_id p {color: blue;}}', $oDoc->render());
|
||||
|
||||
$oDoc = $this->parsedStructureForFile('values');
|
||||
$this->assertSame('#header {margin: 10px 2em 1cm 2%;font-family: Verdana,Helvetica,"Gill Sans",sans-serif;font-size: 10px;color: red !important;background-color: green;background-color: rgba(0,128,0,.7);frequency: 30Hz;}
|
||||
body {color: green;font: 75% "Lucida Grande","Trebuchet MS",Verdana,sans-serif;}', $oDoc->render());
|
||||
foreach ($oDoc->getAllRuleSets() as $oRuleSet) {
|
||||
$oRuleSet->removeRule('font-');
|
||||
}
|
||||
$this->assertSame('#header {margin: 10px 2em 1cm 2%;color: red !important;background-color: green;background-color: rgba(0,128,0,.7);frequency: 30Hz;}
|
||||
body {color: green;}', $oDoc->render());
|
||||
foreach ($oDoc->getAllRuleSets() as $oRuleSet) {
|
||||
$oRuleSet->removeRule('background-');
|
||||
}
|
||||
$this->assertSame('#header {margin: 10px 2em 1cm 2%;color: red !important;frequency: 30Hz;}
|
||||
body {color: green;}', $oDoc->render());
|
||||
}
|
||||
|
||||
function testRuleGetters() {
|
||||
$oDoc = $this->parsedStructureForFile('values');
|
||||
$aBlocks = $oDoc->getAllDeclarationBlocks();
|
||||
$oHeaderBlock = $aBlocks[0];
|
||||
$oBodyBlock = $aBlocks[1];
|
||||
$aHeaderRules = $oHeaderBlock->getRules('background-');
|
||||
$this->assertSame(2, count($aHeaderRules));
|
||||
$this->assertSame('background-color', $aHeaderRules[0]->getRule());
|
||||
$this->assertSame('background-color', $aHeaderRules[1]->getRule());
|
||||
$aHeaderRules = $oHeaderBlock->getRulesAssoc('background-');
|
||||
$this->assertSame(1, count($aHeaderRules));
|
||||
$this->assertSame(true, $aHeaderRules['background-color']->getValue() instanceof \Sabberworm\CSS\Value\Color);
|
||||
$this->assertSame('rgba', $aHeaderRules['background-color']->getValue()->getColorDescription());
|
||||
$oHeaderBlock->removeRule($aHeaderRules['background-color']);
|
||||
$aHeaderRules = $oHeaderBlock->getRules('background-');
|
||||
$this->assertSame(1, count($aHeaderRules));
|
||||
$this->assertSame('green', $aHeaderRules[0]->getValue());
|
||||
}
|
||||
|
||||
function testSlashedValues() {
|
||||
$oDoc = $this->parsedStructureForFile('slashed');
|
||||
$this->assertSame('.test {font: 12px/1.5 Verdana,Arial,sans-serif;border-radius: 5px 10px 5px 10px/10px 5px 10px 5px;}', $oDoc->render());
|
||||
foreach ($oDoc->getAllValues(null) as $mValue) {
|
||||
if ($mValue instanceof Size && $mValue->isSize() && !$mValue->isRelative()) {
|
||||
$mValue->setSize($mValue->getSize() * 3);
|
||||
}
|
||||
}
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oBlock) {
|
||||
$oRule = $oBlock->getRules('font');
|
||||
$oRule = $oRule[0];
|
||||
$oSpaceList = $oRule->getValue();
|
||||
$this->assertEquals(' ', $oSpaceList->getListSeparator());
|
||||
$oSlashList = $oSpaceList->getListComponents();
|
||||
$oCommaList = $oSlashList[1];
|
||||
$oSlashList = $oSlashList[0];
|
||||
$this->assertEquals(',', $oCommaList->getListSeparator());
|
||||
$this->assertEquals('/', $oSlashList->getListSeparator());
|
||||
$oRule = $oBlock->getRules('border-radius');
|
||||
$oRule = $oRule[0];
|
||||
$oSlashList = $oRule->getValue();
|
||||
$this->assertEquals('/', $oSlashList->getListSeparator());
|
||||
$oSpaceList1 = $oSlashList->getListComponents();
|
||||
$oSpaceList2 = $oSpaceList1[1];
|
||||
$oSpaceList1 = $oSpaceList1[0];
|
||||
$this->assertEquals(' ', $oSpaceList1->getListSeparator());
|
||||
$this->assertEquals(' ', $oSpaceList2->getListSeparator());
|
||||
}
|
||||
$this->assertSame('.test {font: 36px/1.5 Verdana,Arial,sans-serif;border-radius: 15px 30px 15px 30px/30px 15px 30px 15px;}', $oDoc->render());
|
||||
}
|
||||
|
||||
function testFunctionSyntax() {
|
||||
$oDoc = $this->parsedStructureForFile('functions');
|
||||
$sExpected = 'div.main {background-image: linear-gradient(#000,#fff);}
|
||||
.collapser::before, .collapser::-moz-before, .collapser::-webkit-before {content: "»";font-size: 1.2em;margin-right: .2em;-moz-transition-property: -moz-transform;-moz-transition-duration: .2s;-moz-transform-origin: center 60%;}
|
||||
.collapser.expanded::before, .collapser.expanded::-moz-before, .collapser.expanded::-webkit-before {-moz-transform: rotate(90deg);}
|
||||
.collapser + * {height: 0;overflow: hidden;-moz-transition-property: height;-moz-transition-duration: .3s;}
|
||||
.collapser.expanded + * {height: auto;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
|
||||
foreach ($oDoc->getAllValues(null, true) as $mValue) {
|
||||
if ($mValue instanceof Size && $mValue->isSize()) {
|
||||
$mValue->setSize($mValue->getSize() * 3);
|
||||
}
|
||||
}
|
||||
$sExpected = str_replace(array('1.2em', '.2em', '60%'), array('3.6em', '.6em', '180%'), $sExpected);
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
|
||||
foreach ($oDoc->getAllValues(null, true) as $mValue) {
|
||||
if ($mValue instanceof Size && !$mValue->isRelative() && !$mValue->isColorComponent()) {
|
||||
$mValue->setSize($mValue->getSize() * 2);
|
||||
}
|
||||
}
|
||||
$sExpected = str_replace(array('.2s', '.3s', '90deg'), array('.4s', '.6s', '180deg'), $sExpected);
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testExpandShorthands() {
|
||||
$oDoc = $this->parsedStructureForFile('expand-shorthands');
|
||||
$sExpected = 'body {font: italic 500 14px/1.618 "Trebuchet MS",Georgia,serif;border: 2px solid #f0f;background: #ccc url("/images/foo.png") no-repeat left top;margin: 1em !important;padding: 2px 6px 3px;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
$oDoc->expandShorthands();
|
||||
$sExpected = 'body {margin-top: 1em !important;margin-right: 1em !important;margin-bottom: 1em !important;margin-left: 1em !important;padding-top: 2px;padding-right: 6px;padding-bottom: 3px;padding-left: 6px;border-top-color: #f0f;border-right-color: #f0f;border-bottom-color: #f0f;border-left-color: #f0f;border-top-style: solid;border-right-style: solid;border-bottom-style: solid;border-left-style: solid;border-top-width: 2px;border-right-width: 2px;border-bottom-width: 2px;border-left-width: 2px;font-style: italic;font-variant: normal;font-weight: 500;font-size: 14px;line-height: 1.618;font-family: "Trebuchet MS",Georgia,serif;background-color: #ccc;background-image: url("/images/foo.png");background-repeat: no-repeat;background-attachment: scroll;background-position: left top;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testCreateShorthands() {
|
||||
$oDoc = $this->parsedStructureForFile('create-shorthands');
|
||||
$sExpected = 'body {font-size: 2em;font-family: Helvetica,Arial,sans-serif;font-weight: bold;border-width: 2px;border-color: #999;border-style: dotted;background-color: #fff;background-image: url("foobar.png");background-repeat: repeat-y;margin-top: 2px;margin-right: 3px;margin-bottom: 4px;margin-left: 5px;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
$oDoc->createShorthands();
|
||||
$sExpected = 'body {background: #fff url("foobar.png") repeat-y;margin: 2px 5px 4px 3px;border: 2px dotted #999;font: bold 2em Helvetica,Arial,sans-serif;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testNamespaces() {
|
||||
$oDoc = $this->parsedStructureForFile('namespaces');
|
||||
$sExpected = '@namespace toto "http://toto.example.org";
|
||||
@namespace "http://example.com/foo";
|
||||
@namespace foo url("http://www.example.com/");
|
||||
@namespace foo url("http://www.example.com/");
|
||||
foo|test {gaga: 1;}
|
||||
|test {gaga: 2;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testInnerColors() {
|
||||
$oDoc = $this->parsedStructureForFile('inner-color');
|
||||
$sExpected = 'test {background: -webkit-gradient(linear,0 0,0 bottom,from(#006cad),to(hsl(202,100%,49%)));}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testPrefixedGradient() {
|
||||
$oDoc = $this->parsedStructureForFile('webkit');
|
||||
$sExpected = '.test {background: -webkit-linear-gradient(top right,white,black);}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testListValueRemoval() {
|
||||
$oDoc = $this->parsedStructureForFile('atrules');
|
||||
foreach ($oDoc->getContents() as $oItem) {
|
||||
if ($oItem instanceof AtRule) {
|
||||
$oDoc->remove($oItem);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$this->assertSame('html, body {font-size: -.6em;}', $oDoc->render());
|
||||
|
||||
$oDoc = $this->parsedStructureForFile('nested');
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oBlock) {
|
||||
$oDoc->removeDeclarationBlockBySelector($oBlock, false);
|
||||
break;
|
||||
}
|
||||
$this->assertSame('html {some-other: -test(val1);}
|
||||
@media screen {html {some: -test(val2);}}
|
||||
#unrelated {other: yes;}', $oDoc->render());
|
||||
|
||||
$oDoc = $this->parsedStructureForFile('nested');
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oBlock) {
|
||||
$oDoc->removeDeclarationBlockBySelector($oBlock, true);
|
||||
break;
|
||||
}
|
||||
$this->assertSame('@media screen {html {some: -test(val2);}}
|
||||
#unrelated {other: yes;}', $oDoc->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\OutputException
|
||||
*/
|
||||
function testSelectorRemoval() {
|
||||
$oDoc = $this->parsedStructureForFile('1readme');
|
||||
$aBlocks = $oDoc->getAllDeclarationBlocks();
|
||||
$oBlock1 = $aBlocks[0];
|
||||
$this->assertSame(true, $oBlock1->removeSelector('html'));
|
||||
$sExpected = '@charset "utf-8";
|
||||
@font-face {font-family: "CrassRoots";src: url("../media/cr.ttf");}
|
||||
body {font-size: 1.6em;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
$this->assertSame(false, $oBlock1->removeSelector('html'));
|
||||
$this->assertSame(true, $oBlock1->removeSelector('body'));
|
||||
// This tries to output a declaration block without a selector and throws.
|
||||
$oDoc->render();
|
||||
}
|
||||
|
||||
function testComments() {
|
||||
$oDoc = $this->parsedStructureForFile('comments');
|
||||
$sExpected = '@import url("some/url.css") screen;
|
||||
.foo, #bar {background-color: #000;}
|
||||
@media screen {#foo.bar {position: absolute;}}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testUrlInFile() {
|
||||
$oDoc = $this->parsedStructureForFile('url', Settings::create()->withMultibyteSupport(true));
|
||||
$sExpected = 'body {background: #fff url("http://somesite.com/images/someimage.gif") repeat top center;}
|
||||
body {background-url: url("http://somesite.com/images/someimage.gif");}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testHexAlphaInFile() {
|
||||
$oDoc = $this->parsedStructureForFile('hex-alpha', Settings::create()->withMultibyteSupport(true));
|
||||
$sExpected = 'div {background: rgba(17,34,51,.27);}
|
||||
div {background: rgba(17,34,51,.27);}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testCalcInFile() {
|
||||
$oDoc = $this->parsedStructureForFile('calc', Settings::create()->withMultibyteSupport(true));
|
||||
$sExpected = 'div {width: calc(100% / 4);}
|
||||
div {margin-top: calc(-120% - 4px);}
|
||||
div {height: -webkit-calc(9 / 16 * 100%) !important;width: -moz-calc(( 50px - 50% ) * 2);}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testCalcNestedInFile() {
|
||||
$oDoc = $this->parsedStructureForFile('calc-nested', Settings::create()->withMultibyteSupport(true));
|
||||
$sExpected = '.test {font-size: calc(( 3 * 4px ) + -2px);top: calc(200px - calc(20 * 3px));}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testGridLineNameInFile() {
|
||||
$oDoc = $this->parsedStructureForFile('grid-linename', Settings::create()->withMultibyteSupport(true));
|
||||
$sExpected = "div {grid-template-columns: [linename] 100px;}\nspan {grid-template-columns: [linename1 linename2] 100px;}";
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testEmptyGridLineNameLenientInFile() {
|
||||
$oDoc = $this->parsedStructureForFile('empty-grid-linename');
|
||||
$sExpected = '.test {grid-template-columns: [] 100px;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testUnmatchedBracesInFile() {
|
||||
$oDoc = $this->parsedStructureForFile('unmatched_braces', Settings::create()->withMultibyteSupport(true));
|
||||
$sExpected = 'button, input, checkbox, textarea {outline: 0;margin: 0;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
function testLineNameFailure() {
|
||||
$this->parsedStructureForFile('-empty-grid-linename', Settings::create()->withLenientParsing(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
function testCalcFailure() {
|
||||
$this->parsedStructureForFile('-calc-no-space-around-minus', Settings::create()->withLenientParsing(false));
|
||||
}
|
||||
|
||||
function testUrlInFileMbOff() {
|
||||
$oDoc = $this->parsedStructureForFile('url', Settings::create()->withMultibyteSupport(false));
|
||||
$sExpected = 'body {background: #fff url("http://somesite.com/images/someimage.gif") repeat top center;}
|
||||
body {background-url: url("http://somesite.com/images/someimage.gif");}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testEmptyFile() {
|
||||
$oDoc = $this->parsedStructureForFile('-empty', Settings::create()->withMultibyteSupport(true));
|
||||
$sExpected = '';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testEmptyFileMbOff() {
|
||||
$oDoc = $this->parsedStructureForFile('-empty', Settings::create()->withMultibyteSupport(false));
|
||||
$sExpected = '';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testCharsetLenient1() {
|
||||
$oDoc = $this->parsedStructureForFile('-charset-after-rule', Settings::create()->withLenientParsing(true));
|
||||
$sExpected = '#id {prop: var(--val);}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testCharsetLenient2() {
|
||||
$oDoc = $this->parsedStructureForFile('-charset-in-block', Settings::create()->withLenientParsing(true));
|
||||
$sExpected = '@media print {}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
function testTrailingWhitespace() {
|
||||
$oDoc = $this->parsedStructureForFile('trailing-whitespace', Settings::create()->withLenientParsing(false));
|
||||
$sExpected = 'div {width: 200px;}';
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
function testCharsetFailure1() {
|
||||
$this->parsedStructureForFile('-charset-after-rule', Settings::create()->withLenientParsing(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
function testCharsetFailure2() {
|
||||
$this->parsedStructureForFile('-charset-in-block', Settings::create()->withLenientParsing(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Sabberworm\CSS\Parsing\SourceException
|
||||
*/
|
||||
function testUnopenedClosingBracketFailure() {
|
||||
$this->parsedStructureForFile('unopened-close-brackets', Settings::create()->withLenientParsing(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a missing property value raises an exception.
|
||||
*
|
||||
* @expectedException \Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
* @covers \Sabberworm\CSS\Value\Value::parseValue()
|
||||
*/
|
||||
function testMissingPropertyValueStrict() {
|
||||
$this->parsedStructureForFile('missing-property-value', Settings::create()->withLenientParsing(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that a missing property value is ignored when in lenient parsing mode.
|
||||
*
|
||||
* @covers \Sabberworm\CSS\Value\Value::parseValue()
|
||||
*/
|
||||
function testMissingPropertyValueLenient() {
|
||||
$parsed = $this->parsedStructureForFile('missing-property-value', Settings::create()->withLenientParsing(true));
|
||||
$rulesets = $parsed->getAllRuleSets();
|
||||
$this->assertCount( 1, $rulesets );
|
||||
$block = $rulesets[0];
|
||||
$this->assertTrue( $block instanceof DeclarationBlock );
|
||||
$this->assertEquals( array( 'div' ), $block->getSelectors() );
|
||||
$rules = $block->getRules();
|
||||
$this->assertCount( 1, $rules );
|
||||
$rule = $rules[0];
|
||||
$this->assertEquals( 'display', $rule->getRule() );
|
||||
$this->assertEquals( 'inline-block', $rule->getValue() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse structure for file.
|
||||
*
|
||||
* @param string $sFileName Filename.
|
||||
* @param null|obJeCt $oSettings Settings.
|
||||
*
|
||||
* @return CSSList\Document Parsed document.
|
||||
*/
|
||||
function parsedStructureForFile($sFileName, $oSettings = null) {
|
||||
$sFile = dirname(__FILE__) . '/../../files' . DIRECTORY_SEPARATOR . "$sFileName.css";
|
||||
$oParser = new Parser(file_get_contents($sFile), $oSettings);
|
||||
return $oParser->parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testFiles
|
||||
*/
|
||||
function testLineNumbersParsing() {
|
||||
$oDoc = $this->parsedStructureForFile('line-numbers');
|
||||
// array key is the expected line number
|
||||
$aExpected = array(
|
||||
1 => array('Sabberworm\CSS\Property\Charset'),
|
||||
3 => array('Sabberworm\CSS\Property\CSSNamespace'),
|
||||
5 => array('Sabberworm\CSS\RuleSet\AtRuleSet'),
|
||||
11 => array('Sabberworm\CSS\RuleSet\DeclarationBlock'),
|
||||
// Line Numbers of the inner declaration blocks
|
||||
17 => array('Sabberworm\CSS\CSSList\KeyFrame', 18, 20),
|
||||
23 => array('Sabberworm\CSS\Property\Import'),
|
||||
25 => array('Sabberworm\CSS\RuleSet\DeclarationBlock')
|
||||
);
|
||||
|
||||
$aActual = array();
|
||||
foreach ($oDoc->getContents() as $oContent) {
|
||||
$aActual[$oContent->getLineNo()] = array(get_class($oContent));
|
||||
if ($oContent instanceof KeyFrame) {
|
||||
foreach ($oContent->getContents() as $block) {
|
||||
$aActual[$oContent->getLineNo()][] = $block->getLineNo();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$aUrlExpected = array(7, 26); // expected line numbers
|
||||
$aUrlActual = array();
|
||||
foreach ($oDoc->getAllValues() as $oValue) {
|
||||
if ($oValue instanceof URL) {
|
||||
$aUrlActual[] = $oValue->getLineNo();
|
||||
}
|
||||
}
|
||||
|
||||
// Checking for the multiline color rule lines 27-31
|
||||
$aExpectedColorLines = array(28, 29, 30);
|
||||
$aDeclBlocks = $oDoc->getAllDeclarationBlocks();
|
||||
// Choose the 2nd one
|
||||
$oDeclBlock = $aDeclBlocks[1];
|
||||
$aRules = $oDeclBlock->getRules();
|
||||
// Choose the 2nd one
|
||||
$oColor = $aRules[1]->getValue();
|
||||
$this->assertEquals(27, $aRules[1]->getLineNo());
|
||||
|
||||
foreach ($oColor->getColor() as $oSize) {
|
||||
$aActualColorLines[] = $oSize->getLineNo();
|
||||
}
|
||||
|
||||
$this->assertEquals($aExpectedColorLines, $aActualColorLines);
|
||||
$this->assertEquals($aUrlExpected, $aUrlActual);
|
||||
$this->assertEquals($aExpected, $aActual);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
* Credit: This test by @sabberworm (from https://github.com/sabberworm/PHP-CSS-Parser/pull/105#issuecomment-229643910 )
|
||||
*/
|
||||
function testUnexpectedTokenExceptionLineNo() {
|
||||
$oParser = new Parser("\ntest: 1;", Settings::create()->beStrict());
|
||||
try {
|
||||
$oParser->parse();
|
||||
} catch (UnexpectedTokenException $e) {
|
||||
$this->assertSame(2, $e->getLineNo());
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
function testIeHacksStrictParsing() {
|
||||
// We can't strictly parse IE hacks.
|
||||
$this->parsedStructureForFile('ie-hacks', Settings::create()->beStrict());
|
||||
}
|
||||
|
||||
function testIeHacksParsing() {
|
||||
$oDoc = $this->parsedStructureForFile('ie-hacks', Settings::create()->withLenientParsing(true));
|
||||
$sExpected = 'p {padding-right: .75rem \9;background-image: none \9;color: red \9\0;background-color: red \9\0;background-color: red \9\0 !important;content: "red \0";content: "red઼";}';
|
||||
$this->assertEquals($sExpected, $oDoc->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testFiles
|
||||
*/
|
||||
function testCommentExtracting() {
|
||||
$oDoc = $this->parsedStructureForFile('comments');
|
||||
$aNodes = $oDoc->getContents();
|
||||
|
||||
// Import property.
|
||||
$importComments = $aNodes[0]->getComments();
|
||||
$this->assertCount(1, $importComments);
|
||||
$this->assertEquals("*\n * Comments Hell.\n ", $importComments[0]->getComment());
|
||||
|
||||
// Declaration block.
|
||||
$fooBarBlock = $aNodes[1];
|
||||
$fooBarBlockComments = $fooBarBlock->getComments();
|
||||
// TODO Support comments in selectors.
|
||||
// $this->assertCount(2, $fooBarBlockComments);
|
||||
// $this->assertEquals("* Number 4 *", $fooBarBlockComments[0]->getComment());
|
||||
// $this->assertEquals("* Number 5 *", $fooBarBlockComments[1]->getComment());
|
||||
|
||||
// Declaration rules.
|
||||
$fooBarRules = $fooBarBlock->getRules();
|
||||
$fooBarRule = $fooBarRules[0];
|
||||
$fooBarRuleComments = $fooBarRule->getComments();
|
||||
$this->assertCount(1, $fooBarRuleComments);
|
||||
$this->assertEquals(" Number 6 ", $fooBarRuleComments[0]->getComment());
|
||||
|
||||
// Media property.
|
||||
$mediaComments = $aNodes[2]->getComments();
|
||||
$this->assertCount(0, $mediaComments);
|
||||
|
||||
// Media children.
|
||||
$mediaRules = $aNodes[2]->getContents();
|
||||
$fooBarComments = $mediaRules[0]->getComments();
|
||||
$this->assertCount(1, $fooBarComments);
|
||||
$this->assertEquals("* Number 10 *", $fooBarComments[0]->getComment());
|
||||
|
||||
// Media -> declaration -> rule.
|
||||
$fooBarRules = $mediaRules[0]->getRules();
|
||||
$fooBarChildComments = $fooBarRules[0]->getComments();
|
||||
$this->assertCount(1, $fooBarChildComments);
|
||||
$this->assertEquals("* Number 10b *", $fooBarChildComments[0]->getComment());
|
||||
}
|
||||
|
||||
function testFlatCommentExtracting() {
|
||||
$parser = new Parser('div {/*Find Me!*/left:10px; text-align:left;}');
|
||||
$doc = $parser->parse();
|
||||
$contents = $doc->getContents();
|
||||
$divRules = $contents[0]->getRules();
|
||||
$comments = $divRules[0]->getComments();
|
||||
$this->assertCount(1, $comments);
|
||||
$this->assertEquals("Find Me!", $comments[0]->getComment());
|
||||
}
|
||||
|
||||
function testTopLevelCommentExtracting() {
|
||||
$parser = new Parser('/*Find Me!*/div {left:10px; text-align:left;}');
|
||||
$doc = $parser->parse();
|
||||
$contents = $doc->getContents();
|
||||
$comments = $contents[0]->getComments();
|
||||
$this->assertCount(1, $comments);
|
||||
$this->assertEquals("Find Me!", $comments[0]->getComment());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
function testMicrosoftFilterStrictParsing() {
|
||||
$oDoc = $this->parsedStructureForFile('ms-filter', Settings::create()->beStrict());
|
||||
}
|
||||
|
||||
function testMicrosoftFilterParsing() {
|
||||
$oDoc = $this->parsedStructureForFile('ms-filter');
|
||||
$sExpected = ".test {filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=\"#80000000\",endColorstr=\"#00000000\",GradientType=1);}";
|
||||
$this->assertSame($sExpected, $oDoc->render());
|
||||
}
|
||||
}
|
||||
267
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/RuleSet/DeclarationBlockTest.php
vendored
Normal file
267
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/RuleSet/DeclarationBlockTest.php
vendored
Normal file
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\RuleSet;
|
||||
|
||||
use Sabberworm\CSS\Parser;
|
||||
use Sabberworm\CSS\Rule\Rule;
|
||||
use Sabberworm\CSS\Value\Size;
|
||||
|
||||
class DeclarationBlockTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @dataProvider expandBorderShorthandProvider
|
||||
* */
|
||||
public function testExpandBorderShorthand($sCss, $sExpected) {
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->expandBorderShorthand();
|
||||
}
|
||||
$this->assertSame(trim((string) $oDoc), $sExpected);
|
||||
}
|
||||
|
||||
public function expandBorderShorthandProvider() {
|
||||
return array(
|
||||
array('body{ border: 2px solid #000 }', 'body {border-width: 2px;border-style: solid;border-color: #000;}'),
|
||||
array('body{ border: none }', 'body {border-style: none;}'),
|
||||
array('body{ border: 2px }', 'body {border-width: 2px;}'),
|
||||
array('body{ border: #f00 }', 'body {border-color: #f00;}'),
|
||||
array('body{ border: 1em solid }', 'body {border-width: 1em;border-style: solid;}'),
|
||||
array('body{ margin: 1em; }', 'body {margin: 1em;}')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider expandFontShorthandProvider
|
||||
* */
|
||||
public function testExpandFontShorthand($sCss, $sExpected) {
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->expandFontShorthand();
|
||||
}
|
||||
$this->assertSame(trim((string) $oDoc), $sExpected);
|
||||
}
|
||||
|
||||
public function expandFontShorthandProvider() {
|
||||
return array(
|
||||
array(
|
||||
'body{ margin: 1em; }',
|
||||
'body {margin: 1em;}'
|
||||
),
|
||||
array(
|
||||
'body {font: 12px serif;}',
|
||||
'body {font-style: normal;font-variant: normal;font-weight: normal;font-size: 12px;line-height: normal;font-family: serif;}'
|
||||
),
|
||||
array(
|
||||
'body {font: italic 12px serif;}',
|
||||
'body {font-style: italic;font-variant: normal;font-weight: normal;font-size: 12px;line-height: normal;font-family: serif;}'
|
||||
),
|
||||
array(
|
||||
'body {font: italic bold 12px serif;}',
|
||||
'body {font-style: italic;font-variant: normal;font-weight: bold;font-size: 12px;line-height: normal;font-family: serif;}'
|
||||
),
|
||||
array(
|
||||
'body {font: italic bold 12px/1.6 serif;}',
|
||||
'body {font-style: italic;font-variant: normal;font-weight: bold;font-size: 12px;line-height: 1.6;font-family: serif;}'
|
||||
),
|
||||
array(
|
||||
'body {font: italic small-caps bold 12px/1.6 serif;}',
|
||||
'body {font-style: italic;font-variant: small-caps;font-weight: bold;font-size: 12px;line-height: 1.6;font-family: serif;}'
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider expandBackgroundShorthandProvider
|
||||
* */
|
||||
public function testExpandBackgroundShorthand($sCss, $sExpected) {
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->expandBackgroundShorthand();
|
||||
}
|
||||
$this->assertSame(trim((string) $oDoc), $sExpected);
|
||||
}
|
||||
|
||||
public function expandBackgroundShorthandProvider() {
|
||||
return array(
|
||||
array('body {border: 1px;}', 'body {border: 1px;}'),
|
||||
array('body {background: #f00;}', 'body {background-color: #f00;background-image: none;background-repeat: repeat;background-attachment: scroll;background-position: 0% 0%;}'),
|
||||
array('body {background: #f00 url("foobar.png");}', 'body {background-color: #f00;background-image: url("foobar.png");background-repeat: repeat;background-attachment: scroll;background-position: 0% 0%;}'),
|
||||
array('body {background: #f00 url("foobar.png") no-repeat;}', 'body {background-color: #f00;background-image: url("foobar.png");background-repeat: no-repeat;background-attachment: scroll;background-position: 0% 0%;}'),
|
||||
array('body {background: #f00 url("foobar.png") no-repeat center;}', 'body {background-color: #f00;background-image: url("foobar.png");background-repeat: no-repeat;background-attachment: scroll;background-position: center center;}'),
|
||||
array('body {background: #f00 url("foobar.png") no-repeat top left;}', 'body {background-color: #f00;background-image: url("foobar.png");background-repeat: no-repeat;background-attachment: scroll;background-position: top left;}'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider expandDimensionsShorthandProvider
|
||||
* */
|
||||
public function testExpandDimensionsShorthand($sCss, $sExpected) {
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->expandDimensionsShorthand();
|
||||
}
|
||||
$this->assertSame(trim((string) $oDoc), $sExpected);
|
||||
}
|
||||
|
||||
public function expandDimensionsShorthandProvider() {
|
||||
return array(
|
||||
array('body {border: 1px;}', 'body {border: 1px;}'),
|
||||
array('body {margin-top: 1px;}', 'body {margin-top: 1px;}'),
|
||||
array('body {margin: 1em;}', 'body {margin-top: 1em;margin-right: 1em;margin-bottom: 1em;margin-left: 1em;}'),
|
||||
array('body {margin: 1em 2em;}', 'body {margin-top: 1em;margin-right: 2em;margin-bottom: 1em;margin-left: 2em;}'),
|
||||
array('body {margin: 1em 2em 3em;}', 'body {margin-top: 1em;margin-right: 2em;margin-bottom: 3em;margin-left: 2em;}'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider createBorderShorthandProvider
|
||||
* */
|
||||
public function testCreateBorderShorthand($sCss, $sExpected) {
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->createBorderShorthand();
|
||||
}
|
||||
$this->assertSame(trim((string) $oDoc), $sExpected);
|
||||
}
|
||||
|
||||
public function createBorderShorthandProvider() {
|
||||
return array(
|
||||
array('body {border-width: 2px;border-style: solid;border-color: #000;}', 'body {border: 2px solid #000;}'),
|
||||
array('body {border-style: none;}', 'body {border: none;}'),
|
||||
array('body {border-width: 1em;border-style: solid;}', 'body {border: 1em solid;}'),
|
||||
array('body {margin: 1em;}', 'body {margin: 1em;}')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider createFontShorthandProvider
|
||||
* */
|
||||
public function testCreateFontShorthand($sCss, $sExpected) {
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->createFontShorthand();
|
||||
}
|
||||
$this->assertSame(trim((string) $oDoc), $sExpected);
|
||||
}
|
||||
|
||||
public function createFontShorthandProvider() {
|
||||
return array(
|
||||
array('body {font-size: 12px; font-family: serif}', 'body {font: 12px serif;}'),
|
||||
array('body {font-size: 12px; font-family: serif; font-style: italic;}', 'body {font: italic 12px serif;}'),
|
||||
array('body {font-size: 12px; font-family: serif; font-style: italic; font-weight: bold;}', 'body {font: italic bold 12px serif;}'),
|
||||
array('body {font-size: 12px; font-family: serif; font-style: italic; font-weight: bold; line-height: 1.6;}', 'body {font: italic bold 12px/1.6 serif;}'),
|
||||
array('body {font-size: 12px; font-family: serif; font-style: italic; font-weight: bold; line-height: 1.6; font-variant: small-caps;}', 'body {font: italic small-caps bold 12px/1.6 serif;}'),
|
||||
array('body {margin: 1em;}', 'body {margin: 1em;}')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider createDimensionsShorthandProvider
|
||||
* */
|
||||
public function testCreateDimensionsShorthand($sCss, $sExpected) {
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->createDimensionsShorthand();
|
||||
}
|
||||
$this->assertSame(trim((string) $oDoc), $sExpected);
|
||||
}
|
||||
|
||||
public function createDimensionsShorthandProvider() {
|
||||
return array(
|
||||
array('body {border: 1px;}', 'body {border: 1px;}'),
|
||||
array('body {margin-top: 1px;}', 'body {margin-top: 1px;}'),
|
||||
array('body {margin-top: 1em; margin-right: 1em; margin-bottom: 1em; margin-left: 1em;}', 'body {margin: 1em;}'),
|
||||
array('body {margin-top: 1em; margin-right: 2em; margin-bottom: 1em; margin-left: 2em;}', 'body {margin: 1em 2em;}'),
|
||||
array('body {margin-top: 1em; margin-right: 2em; margin-bottom: 3em; margin-left: 2em;}', 'body {margin: 1em 2em 3em;}'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider createBackgroundShorthandProvider
|
||||
* */
|
||||
public function testCreateBackgroundShorthand($sCss, $sExpected) {
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
foreach ($oDoc->getAllDeclarationBlocks() as $oDeclaration) {
|
||||
$oDeclaration->createBackgroundShorthand();
|
||||
}
|
||||
$this->assertSame(trim((string) $oDoc), $sExpected);
|
||||
}
|
||||
|
||||
public function createBackgroundShorthandProvider() {
|
||||
return array(
|
||||
array('body {border: 1px;}', 'body {border: 1px;}'),
|
||||
array('body {background-color: #f00;}', 'body {background: #f00;}'),
|
||||
array('body {background-color: #f00;background-image: url(foobar.png);}', 'body {background: #f00 url("foobar.png");}'),
|
||||
array('body {background-color: #f00;background-image: url(foobar.png);background-repeat: no-repeat;}', 'body {background: #f00 url("foobar.png") no-repeat;}'),
|
||||
array('body {background-color: #f00;background-image: url(foobar.png);background-repeat: no-repeat;}', 'body {background: #f00 url("foobar.png") no-repeat;}'),
|
||||
array('body {background-color: #f00;background-image: url(foobar.png);background-repeat: no-repeat;background-position: center;}', 'body {background: #f00 url("foobar.png") no-repeat center;}'),
|
||||
array('body {background-color: #f00;background-image: url(foobar.png);background-repeat: no-repeat;background-position: top left;}', 'body {background: #f00 url("foobar.png") no-repeat top left;}'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testOverrideRules() {
|
||||
$sCss = '.wrapper { left: 10px; text-align: left; }';
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
$oRule = new Rule('right');
|
||||
$oRule->setValue('-10px');
|
||||
$aContents = $oDoc->getContents();
|
||||
$oWrapper = $aContents[0];
|
||||
|
||||
$this->assertCount(2, $oWrapper->getRules());
|
||||
$aContents[0]->setRules(array($oRule));
|
||||
|
||||
$aRules = $oWrapper->getRules();
|
||||
$this->assertCount(1, $aRules);
|
||||
$this->assertEquals('right', $aRules[0]->getRule());
|
||||
$this->assertEquals('-10px', $aRules[0]->getValue());
|
||||
}
|
||||
|
||||
public function testRuleInsertion() {
|
||||
$sCss = '.wrapper { left: 10px; text-align: left; }';
|
||||
$oParser = new Parser($sCss);
|
||||
$oDoc = $oParser->parse();
|
||||
$aContents = $oDoc->getContents();
|
||||
$oWrapper = $aContents[0];
|
||||
|
||||
$oFirst = $oWrapper->getRules('left');
|
||||
$this->assertCount(1, $oFirst);
|
||||
$oFirst = $oFirst[0];
|
||||
|
||||
$oSecond = $oWrapper->getRules('text-');
|
||||
$this->assertCount(1, $oSecond);
|
||||
$oSecond = $oSecond[0];
|
||||
|
||||
$oBefore = new Rule('left');
|
||||
$oBefore->setValue(new Size(16, 'em'));
|
||||
|
||||
$oMiddle = new Rule('text-align');
|
||||
$oMiddle->setValue(new Size(1));
|
||||
|
||||
$oAfter = new Rule('border-bottom-width');
|
||||
$oAfter->setValue(new Size(1, 'px'));
|
||||
|
||||
$oWrapper->addRule($oAfter);
|
||||
$oWrapper->addRule($oBefore, $oFirst);
|
||||
$oWrapper->addRule($oMiddle, $oSecond);
|
||||
|
||||
$aRules = $oWrapper->getRules();
|
||||
|
||||
$this->assertSame($oBefore, $aRules[0]);
|
||||
$this->assertSame($oFirst, $aRules[1]);
|
||||
$this->assertSame($oMiddle, $aRules[2]);
|
||||
$this->assertSame($oSecond, $aRules[3]);
|
||||
$this->assertSame($oAfter, $aRules[4]);
|
||||
|
||||
$this->assertSame('.wrapper {left: 16em;left: 10px;text-align: 1;text-align: left;border-bottom-width: 1px;}', $oDoc->render());
|
||||
}
|
||||
|
||||
}
|
||||
76
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/RuleSet/LenientParsingTest.php
vendored
Normal file
76
vendor/sabberworm/php-css-parser/tests/Sabberworm/CSS/RuleSet/LenientParsingTest.php
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Sabberworm\CSS\RuleSet;
|
||||
|
||||
use Sabberworm\CSS\Parser;
|
||||
use Sabberworm\CSS\Settings;
|
||||
|
||||
class LenientParsingTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
public function testFaultToleranceOff() {
|
||||
$sFile = dirname(__FILE__) . '/../../../files' . DIRECTORY_SEPARATOR . "-fault-tolerance.css";
|
||||
$oParser = new Parser(file_get_contents($sFile), Settings::create()->beStrict());
|
||||
$oParser->parse();
|
||||
}
|
||||
|
||||
public function testFaultToleranceOn() {
|
||||
$sFile = dirname(__FILE__) . '/../../../files' . DIRECTORY_SEPARATOR . "-fault-tolerance.css";
|
||||
$oParser = new Parser(file_get_contents($sFile), Settings::create()->withLenientParsing(true));
|
||||
$oResult = $oParser->parse();
|
||||
$this->assertSame('.test1 {}'."\n".'.test2 {hello: 2.2;hello: 2000000000000.2;}'."\n".'#test {}'."\n".'#test2 {help: none;}', $oResult->render());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
public function testEndToken() {
|
||||
$sFile = dirname(__FILE__) . '/../../../files' . DIRECTORY_SEPARATOR . "-end-token.css";
|
||||
$oParser = new Parser(file_get_contents($sFile), Settings::create()->beStrict());
|
||||
$oParser->parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Sabberworm\CSS\Parsing\UnexpectedTokenException
|
||||
*/
|
||||
public function testEndToken2() {
|
||||
$sFile = dirname(__FILE__) . '/../../../files' . DIRECTORY_SEPARATOR . "-end-token-2.css";
|
||||
$oParser = new Parser(file_get_contents($sFile), Settings::create()->beStrict());
|
||||
$oParser->parse();
|
||||
}
|
||||
|
||||
public function testEndTokenPositive() {
|
||||
$sFile = dirname(__FILE__) . '/../../../files' . DIRECTORY_SEPARATOR . "-end-token.css";
|
||||
$oParser = new Parser(file_get_contents($sFile), Settings::create()->withLenientParsing(true));
|
||||
$oResult = $oParser->parse();
|
||||
$this->assertSame("", $oResult->render());
|
||||
}
|
||||
|
||||
public function testEndToken2Positive() {
|
||||
$sFile = dirname(__FILE__) . '/../../../files' . DIRECTORY_SEPARATOR . "-end-token-2.css";
|
||||
$oParser = new Parser(file_get_contents($sFile), Settings::create()->withLenientParsing(true));
|
||||
$oResult = $oParser->parse();
|
||||
$this->assertSame('#home .bg-layout {background-image: url("/bundles/main/img/bg1.png?5");}', $oResult->render());
|
||||
}
|
||||
|
||||
public function testLocaleTrap() {
|
||||
setlocale(LC_ALL, "pt_PT", "no");
|
||||
$sFile = dirname(__FILE__) . '/../../../files' . DIRECTORY_SEPARATOR . "-fault-tolerance.css";
|
||||
$oParser = new Parser(file_get_contents($sFile), Settings::create()->withLenientParsing(true));
|
||||
$oResult = $oParser->parse();
|
||||
$this->assertSame('.test1 {}'."\n".'.test2 {hello: 2.2;hello: 2000000000000.2;}'."\n".'#test {}'."\n".'#test2 {help: none;}', $oResult->render());
|
||||
}
|
||||
|
||||
public function testCaseInsensitivity() {
|
||||
$sFile = dirname(__FILE__) . '/../../../files' . DIRECTORY_SEPARATOR . "case-insensitivity.css";
|
||||
$oParser = new Parser(file_get_contents($sFile));
|
||||
$oResult = $oParser->parse();
|
||||
$this->assertSame('@charset "utf-8";
|
||||
@import url("test.css");
|
||||
@media screen {}
|
||||
#myid {case: insensitive !important;frequency: 30Hz;font-size: 1em;color: #ff0;color: hsl(40,40%,30%);font-family: Arial;}', $oResult->render());
|
||||
}
|
||||
|
||||
}
|
||||
10
vendor/sabberworm/php-css-parser/tests/bootstrap.php
vendored
Normal file
10
vendor/sabberworm/php-css-parser/tests/bootstrap.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
spl_autoload_register(function($class)
|
||||
{
|
||||
$file = __DIR__.'/../lib/'.strtr($class, '\\', '/').'.php';
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
1
vendor/sabberworm/php-css-parser/tests/files/-calc-no-space-around-minus.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/-calc-no-space-around-minus.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
div { width: calc(50% -8px); }
|
||||
5
vendor/sabberworm/php-css-parser/tests/files/-charset-after-rule.css
vendored
Normal file
5
vendor/sabberworm/php-css-parser/tests/files/-charset-after-rule.css
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#id {
|
||||
prop: var(--val);
|
||||
}
|
||||
|
||||
@charset 'utf-16';
|
||||
3
vendor/sabberworm/php-css-parser/tests/files/-charset-in-block.css
vendored
Normal file
3
vendor/sabberworm/php-css-parser/tests/files/-charset-in-block.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
@media print {
|
||||
@charset 'utf-16';
|
||||
}
|
||||
1
vendor/sabberworm/php-css-parser/tests/files/-empty-grid-linename.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/-empty-grid-linename.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.test { grid-template-columns: [] 100px; }
|
||||
0
vendor/sabberworm/php-css-parser/tests/files/-empty.css
vendored
Normal file
0
vendor/sabberworm/php-css-parser/tests/files/-empty.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/-end-token-2.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/-end-token-2.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
#home .bg-layout { background-image: url(/bundles/main/img/bg1.png?5);};
|
||||
1
vendor/sabberworm/php-css-parser/tests/files/-end-token.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/-end-token.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/* Test comment
|
||||
15
vendor/sabberworm/php-css-parser/tests/files/-fault-tolerance.css
vendored
Normal file
15
vendor/sabberworm/php-css-parser/tests/files/-fault-tolerance.css
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
.test1 {
|
||||
//gaga: hello;
|
||||
}
|
||||
|
||||
.test2 {
|
||||
*hello: 1;
|
||||
hello: 2.2;
|
||||
hello: 2000000000000.2;
|
||||
}
|
||||
|
||||
#test {
|
||||
#hello: 1}
|
||||
|
||||
#test2 {
|
||||
help: none;
|
||||
9
vendor/sabberworm/php-css-parser/tests/files/-tobedone.css
vendored
Normal file
9
vendor/sabberworm/php-css-parser/tests/files/-tobedone.css
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
.some[selectors-may='contain-a-{'] {
|
||||
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 200px) {
|
||||
.test {
|
||||
prop: val;
|
||||
}
|
||||
}
|
||||
10
vendor/sabberworm/php-css-parser/tests/files/1readme.css
vendored
Normal file
10
vendor/sabberworm/php-css-parser/tests/files/1readme.css
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
@charset "utf-8";
|
||||
|
||||
@font-face {
|
||||
font-family: "CrassRoots";
|
||||
src: url("../media/cr.ttf")
|
||||
}
|
||||
|
||||
html, body {
|
||||
font-size: 1.6em
|
||||
}
|
||||
5
vendor/sabberworm/php-css-parser/tests/files/2readme.css
vendored
Normal file
5
vendor/sabberworm/php-css-parser/tests/files/2readme.css
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
#header {
|
||||
margin: 10px 2em 1cm 2%;
|
||||
font-family: Verdana, Helvetica, "Gill Sans", sans-serif;
|
||||
color: red !important;
|
||||
}
|
||||
57
vendor/sabberworm/php-css-parser/tests/files/atrules.css
vendored
Normal file
57
vendor/sabberworm/php-css-parser/tests/files/atrules.css
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
@charset "utf-8";
|
||||
|
||||
@font-face {
|
||||
font-family: "CrassRoots";
|
||||
src: url("../media/cr.ttf")
|
||||
}
|
||||
|
||||
html, body {
|
||||
font-size: -0.6em
|
||||
}
|
||||
|
||||
@keyframes mymove {
|
||||
from { top: 0px; }
|
||||
to { top: 200px; }
|
||||
}
|
||||
|
||||
@-moz-keyframes some-move {
|
||||
from { top: 0px; }
|
||||
to { top: 200px; }
|
||||
}
|
||||
|
||||
@supports ( (perspective: 10px) or (-moz-perspective: 10px) or (-webkit-perspective: 10px) or (-ms-perspective: 10px) or (-o-perspective: 10px) ) {
|
||||
body {
|
||||
font-family: 'Helvetica';
|
||||
}
|
||||
}
|
||||
|
||||
@page :pseudo-class {
|
||||
margin:2in;
|
||||
}
|
||||
|
||||
@-moz-document url(http://www.w3.org/),
|
||||
url-prefix(http://www.w3.org/Style/),
|
||||
domain(mozilla.org),
|
||||
regexp("https:.*") {
|
||||
/* CSS rules here apply to:
|
||||
+ The page "http://www.w3.org/".
|
||||
+ Any page whose URL begins with "http://www.w3.org/Style/"
|
||||
+ Any page whose URL's host is "mozilla.org" or ends with
|
||||
".mozilla.org"
|
||||
+ Any page whose URL starts with "https:" */
|
||||
|
||||
/* make the above-mentioned pages really ugly */
|
||||
body { color: purple; background: yellow; }
|
||||
}
|
||||
|
||||
@media screen and (orientation: landscape) {
|
||||
@-ms-viewport {
|
||||
width: 1024px;
|
||||
height: 768px;
|
||||
}
|
||||
/* CSS for landscape layout goes here */
|
||||
}
|
||||
|
||||
@region-style #intro {
|
||||
p { color: blue; }
|
||||
}
|
||||
4
vendor/sabberworm/php-css-parser/tests/files/calc-nested.css
vendored
Normal file
4
vendor/sabberworm/php-css-parser/tests/files/calc-nested.css
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.test {
|
||||
font-size: calc((3 * 4px) + -2px);
|
||||
top: calc(200px - calc(20 * 3px));
|
||||
}
|
||||
6
vendor/sabberworm/php-css-parser/tests/files/calc.css
vendored
Normal file
6
vendor/sabberworm/php-css-parser/tests/files/calc.css
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
div { width: calc(100% / 4); }
|
||||
div { margin-top: calc(-120% - 4px); }
|
||||
div {
|
||||
height: -webkit-calc(9/16 * 100%)!important;
|
||||
width: -moz-calc((50px - 50%)*2);
|
||||
}
|
||||
15
vendor/sabberworm/php-css-parser/tests/files/case-insensitivity.css
vendored
Normal file
15
vendor/sabberworm/php-css-parser/tests/files/case-insensitivity.css
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
@CharSet "utf-8";
|
||||
@IMPORT uRL(test.css);
|
||||
|
||||
@MEDIA screen {
|
||||
|
||||
}
|
||||
|
||||
#myid {
|
||||
CaSe: insensitive !imPORTANT;
|
||||
frequency: 30hz;
|
||||
font-size: 1EM;
|
||||
color: RGB(255, 255, 0);
|
||||
color: hSL(40, 40%, 30%);
|
||||
font-Family: Arial; /* The value needs to remain capitalized */
|
||||
}
|
||||
12
vendor/sabberworm/php-css-parser/tests/files/colortest.css
vendored
Normal file
12
vendor/sabberworm/php-css-parser/tests/files/colortest.css
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
#mine {
|
||||
color: red;
|
||||
border-color: rgb(10, 100, 230);
|
||||
border-color: rgba(10, 100, 231, 0.3);
|
||||
outline-color: #222;
|
||||
background-color: #232323;
|
||||
}
|
||||
|
||||
#yours {
|
||||
background-color: hsl(220, 10%, 220%);
|
||||
background-color: hsla(220, 10%, 220%, 0.3);
|
||||
}
|
||||
17
vendor/sabberworm/php-css-parser/tests/files/comments.css
vendored
Normal file
17
vendor/sabberworm/php-css-parser/tests/files/comments.css
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Comments Hell.
|
||||
*/
|
||||
@import /* Number 1 */"some/url.css"/* Number 2 */ screen/* Number 3 */;
|
||||
|
||||
.foo, /* Number 4 */ #bar/* Number 5 */ {
|
||||
background-color/* Number 6 */: #000/* Number 7 */;
|
||||
}
|
||||
|
||||
@media /* Number 8 */screen /* Number 9 */{
|
||||
/** Number 10 **/
|
||||
#foo.bar {
|
||||
/** Number 10b **/
|
||||
position: absolute;/**/
|
||||
}
|
||||
}
|
||||
/** Number 11 **/
|
||||
6
vendor/sabberworm/php-css-parser/tests/files/create-shorthands.css
vendored
Normal file
6
vendor/sabberworm/php-css-parser/tests/files/create-shorthands.css
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
body {
|
||||
font-size: 2em; font-family: Helvetica,Arial,sans-serif; font-weight: bold;
|
||||
border-width: 2px; border-color: #999; border-style: dotted;
|
||||
background-color: #fff; background-image: url('foobar.png'); background-repeat: repeat-y;
|
||||
margin-top: 2px; margin-right: 3px; margin-bottom: 4px; margin-left: 5px;
|
||||
}
|
||||
1
vendor/sabberworm/php-css-parser/tests/files/docuwiki.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/docuwiki.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
div.dokuwiki div.ajax_qsearch{position:absolute;right:237px;;width:200px;opacity:0.9;display:none;font-size:80%;line-height:1.2em;border:1px solid #8cacbb;background-color:#f7f9fa;text-align:left;padding:4px;}
|
||||
1
vendor/sabberworm/php-css-parser/tests/files/empty-grid-linename.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/empty-grid-linename.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.test { grid-template-columns: [] 100px; }
|
||||
7
vendor/sabberworm/php-css-parser/tests/files/expand-shorthands.css
vendored
Normal file
7
vendor/sabberworm/php-css-parser/tests/files/expand-shorthands.css
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
body {
|
||||
font: italic 500 14px/1.618 "Trebuchet MS", Georgia, serif;
|
||||
border: 2px solid #f0f;
|
||||
background: #ccc url("/images/foo.png") no-repeat left top;
|
||||
margin: 1em !important;
|
||||
padding: 2px 6px 3px;
|
||||
}
|
||||
21
vendor/sabberworm/php-css-parser/tests/files/functions.css
vendored
Normal file
21
vendor/sabberworm/php-css-parser/tests/files/functions.css
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
div.main { background-image: linear-gradient(#000, #fff) }
|
||||
.collapser::before,
|
||||
.collapser::-moz-before,
|
||||
.collapser::-webkit-before {
|
||||
content: "»";
|
||||
font-size: 1.2em;
|
||||
margin-right: .2em;
|
||||
-moz-transition-property: -moz-transform;
|
||||
-moz-transition-duration: .2s;
|
||||
-moz-transform-origin: center 60%;
|
||||
}
|
||||
.collapser.expanded::before,
|
||||
.collapser.expanded::-moz-before,
|
||||
.collapser.expanded::-webkit-before { -moz-transform: rotate(90deg) }
|
||||
.collapser + * {
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
-moz-transition-property: height;
|
||||
-moz-transition-duration: .3s;
|
||||
}
|
||||
.collapser.expanded + * { height: auto }
|
||||
2
vendor/sabberworm/php-css-parser/tests/files/grid-linename.css
vendored
Normal file
2
vendor/sabberworm/php-css-parser/tests/files/grid-linename.css
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
div { grid-template-columns: [ linename ] 100px; }
|
||||
span { grid-template-columns: [ linename1 linename2 ] 100px; }
|
||||
2
vendor/sabberworm/php-css-parser/tests/files/hex-alpha.css
vendored
Normal file
2
vendor/sabberworm/php-css-parser/tests/files/hex-alpha.css
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
div { background: #1234; }
|
||||
div { background: #11223344; }
|
||||
9
vendor/sabberworm/php-css-parser/tests/files/ie-hacks.css
vendored
Normal file
9
vendor/sabberworm/php-css-parser/tests/files/ie-hacks.css
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
p {
|
||||
padding-right: .75rem \9;
|
||||
background-image: none \9;
|
||||
color:red\9\0;
|
||||
background-color:red \9 \0;
|
||||
background-color:red \9 \0 !important;
|
||||
content: "red \9\0";
|
||||
content: "red\0abc";
|
||||
}
|
||||
6
vendor/sabberworm/php-css-parser/tests/files/ie.css
vendored
Normal file
6
vendor/sabberworm/php-css-parser/tests/files/ie.css
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.nav-thumb-wrapper:hover img, a.activeSlide img {
|
||||
filter: alpha(opacity=100);
|
||||
-moz-opacity: 1;
|
||||
-khtml-opacity: 1;
|
||||
opacity: 1;
|
||||
}
|
||||
8
vendor/sabberworm/php-css-parser/tests/files/important.css
vendored
Normal file
8
vendor/sabberworm/php-css-parser/tests/files/important.css
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
div.rating-cancel,div.star-rating{float:left;width:17px;height:15px;text-indent:-999em;cursor:pointer;display:block;background:transparent;overflow:hidden}
|
||||
div.rating-cancel,div.rating-cancel a{background:url(images/delete.gif) no-repeat 0 -16px}
|
||||
div.star-rating,div.star-rating a{background:url(images/star.gif) no-repeat 0 0px}
|
||||
div.rating-cancel a,div.star-rating a{display:block;width:16px;height:100%;background-position:0 0px;border:0}
|
||||
div.star-rating-on a{background-position:0 -16px!important}
|
||||
div.star-rating-hover a{background-position:0 -32px}
|
||||
div.star-rating-readonly a{cursor:default !important}
|
||||
div.star-rating{background:transparent!important; overflow:hidden!important}
|
||||
3
vendor/sabberworm/php-css-parser/tests/files/inner-color.css
vendored
Normal file
3
vendor/sabberworm/php-css-parser/tests/files/inner-color.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
test {
|
||||
background: -webkit-gradient(linear, 0 0, 0 bottom, from(#006cad), to(hsl(202, 100%, 49%)));
|
||||
}
|
||||
32
vendor/sabberworm/php-css-parser/tests/files/line-numbers.css
vendored
Normal file
32
vendor/sabberworm/php-css-parser/tests/files/line-numbers.css
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
@charset "utf-8"; /* line 1 */
|
||||
|
||||
@namespace "http://toto.example.org"; /* line 3 */
|
||||
|
||||
@font-face { /* line 5 */
|
||||
font-family: "CrassRoots";
|
||||
src: url("http://example.com/media/cr.ttf") /* line 7 */
|
||||
}
|
||||
|
||||
|
||||
#header { /* line 11 */
|
||||
margin: 10px 2em 1cm 2%;
|
||||
font-family: Verdana, Helvetica, "Gill Sans", sans-serif;
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
@keyframes mymove { /* line 17 */
|
||||
from { top: 0px; } /* line 18 */
|
||||
|
||||
to { top: 200px; } /* line 20 */
|
||||
}
|
||||
|
||||
@IMPORT uRL(test.css); /* line 23 */
|
||||
|
||||
body {
|
||||
background: #FFFFFF url("http://somesite.com/images/someimage.gif") repeat top center; /* line 25 */
|
||||
color: rgb( /* line 27 */
|
||||
233, /* line 28 */
|
||||
100, /* line 29 */
|
||||
450 /* line 30 */
|
||||
);
|
||||
}
|
||||
4
vendor/sabberworm/php-css-parser/tests/files/missing-property-value.css
vendored
Normal file
4
vendor/sabberworm/php-css-parser/tests/files/missing-property-value.css
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
div {
|
||||
display: inline-block;
|
||||
display:
|
||||
}
|
||||
1
vendor/sabberworm/php-css-parser/tests/files/ms-filter.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/ms-filter.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.test {filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);}
|
||||
18
vendor/sabberworm/php-css-parser/tests/files/namespaces.css
vendored
Normal file
18
vendor/sabberworm/php-css-parser/tests/files/namespaces.css
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/* From the spec at http://www.w3.org/TR/css3-namespace/ */
|
||||
|
||||
@namespace toto "http://toto.example.org";
|
||||
@namespace "http://example.com/foo";
|
||||
|
||||
|
||||
/* From an introduction at http://www.blooberry.com/indexdot/css/syntax/atrules/namespace.htm */
|
||||
@namespace foo url("http://www.example.com/");
|
||||
@namespace foo url('http://www.example.com/');
|
||||
|
||||
|
||||
foo|test {
|
||||
gaga: 1;
|
||||
}
|
||||
|
||||
|test {
|
||||
gaga: 2;
|
||||
}
|
||||
17
vendor/sabberworm/php-css-parser/tests/files/nested.css
vendored
Normal file
17
vendor/sabberworm/php-css-parser/tests/files/nested.css
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
html {
|
||||
some: -test(val1);
|
||||
}
|
||||
|
||||
html {
|
||||
some-other: -test(val1);
|
||||
}
|
||||
|
||||
@media screen {
|
||||
html {
|
||||
some: -test(val2);
|
||||
}
|
||||
}
|
||||
|
||||
#unrelated {
|
||||
other: yes;
|
||||
}
|
||||
4
vendor/sabberworm/php-css-parser/tests/files/slashed.css
vendored
Normal file
4
vendor/sabberworm/php-css-parser/tests/files/slashed.css
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.test {
|
||||
font: 12px/1.5 Verdana, Arial, sans-serif;
|
||||
border-radius: 5px 10px 5px 10px / 10px 5px 10px 5px;
|
||||
}
|
||||
7
vendor/sabberworm/php-css-parser/tests/files/specificity.css
vendored
Normal file
7
vendor/sabberworm/php-css-parser/tests/files/specificity.css
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
#test .help,
|
||||
#file,
|
||||
.help:hover,
|
||||
li.green,
|
||||
ol li::before {
|
||||
font-family: Helvetica;
|
||||
}
|
||||
2
vendor/sabberworm/php-css-parser/tests/files/trailing-whitespace.css
vendored
Normal file
2
vendor/sabberworm/php-css-parser/tests/files/trailing-whitespace.css
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
div { width: 200px; }
|
||||
|
||||
3
vendor/sabberworm/php-css-parser/tests/files/unicode-range.css
vendored
Normal file
3
vendor/sabberworm/php-css-parser/tests/files/unicode-range.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
@font-face {
|
||||
unicode-range: U+0100-024F, U+0259, U+1E??-2EFF, U+202F;
|
||||
}
|
||||
12
vendor/sabberworm/php-css-parser/tests/files/unicode.css
vendored
Normal file
12
vendor/sabberworm/php-css-parser/tests/files/unicode.css
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
.test-1 { content: "\20"; } /* Same as " " */
|
||||
.test-2 { content: "\E9"; } /* Same as "é" */
|
||||
.test-3 { content: "\0020"; } /* Same as " " */
|
||||
.test-5 { content: "\6C34" } /* Same as "水" */
|
||||
.test-6 { content: "\00A5" } /* Same as "¥" */
|
||||
.test-7 { content: '\a' } /* Same as "\A" (Newline) */
|
||||
.test-8 { content: "\"\22" } /* Same as "\"\"" */
|
||||
.test-9 { content: "\"\27" } /* Same as ""\"\'"" */
|
||||
.test-10 { content: "\'\\" } /* Same as "'\" */
|
||||
.test-11 { content: "\test" } /* Same as "test" */
|
||||
|
||||
.test-4 { content: "\1D11E" } /* Beyond the Basic Multilingual Plane */
|
||||
18
vendor/sabberworm/php-css-parser/tests/files/unmatched_braces.css
vendored
Normal file
18
vendor/sabberworm/php-css-parser/tests/files/unmatched_braces.css
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
button,input,checkbox,textarea {
|
||||
outline: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio:3/@media all and (orientation:portrait) {
|
||||
#wrapper {
|
||||
max-width:640px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (orientation: landscape) {
|
||||
#wrapper {
|
||||
max-width:640px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
3
vendor/sabberworm/php-css-parser/tests/files/unopened-close-brackets.css
vendored
Normal file
3
vendor/sabberworm/php-css-parser/tests/files/unopened-close-brackets.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
}}}.blue{
|
||||
background: #00F;
|
||||
}
|
||||
4
vendor/sabberworm/php-css-parser/tests/files/url.css
vendored
Normal file
4
vendor/sabberworm/php-css-parser/tests/files/url.css
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
body { background: #FFFFFF url("http://somesite.com/images/someimage.gif") repeat top center; }
|
||||
body {
|
||||
background-url: url("http://somesite.com/images/someimage.gif");
|
||||
}
|
||||
14
vendor/sabberworm/php-css-parser/tests/files/values.css
vendored
Normal file
14
vendor/sabberworm/php-css-parser/tests/files/values.css
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
#header {
|
||||
margin: 10px 2em 1cm 2%;
|
||||
font-family: Verdana, Helvetica, "Gill Sans", sans-serif;
|
||||
font-size: 10px;
|
||||
color: red !important;
|
||||
background-color: green;
|
||||
background-color: rgba(0,128,0,0.7);
|
||||
frequency: 30Hz;
|
||||
}
|
||||
|
||||
body {
|
||||
color: green;
|
||||
font: 75% "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
|
||||
}
|
||||
1
vendor/sabberworm/php-css-parser/tests/files/webkit.css
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/files/webkit.css
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.test { background:-webkit-linear-gradient(top right, white, black)}
|
||||
3
vendor/sabberworm/php-css-parser/tests/files/whitespace.css
vendored
Normal file
3
vendor/sabberworm/php-css-parser/tests/files/whitespace.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.test {
|
||||
background-image : url ( 4px ) ;
|
||||
}
|
||||
1
vendor/sabberworm/php-css-parser/tests/phpunit.xml
vendored
Normal file
1
vendor/sabberworm/php-css-parser/tests/phpunit.xml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<phpunit bootstrap="bootstrap.php"></phpunit>
|
||||
20
vendor/sabberworm/php-css-parser/tests/quickdump.php
vendored
Normal file
20
vendor/sabberworm/php-css-parser/tests/quickdump.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
require_once(dirname(__FILE__).'/bootstrap.php');
|
||||
|
||||
$sSource = file_get_contents('php://stdin');
|
||||
$oParser = new Sabberworm\CSS\Parser($sSource);
|
||||
|
||||
$oDoc = $oParser->parse();
|
||||
echo "\n".'#### Input'."\n\n```css\n";
|
||||
print $sSource;
|
||||
|
||||
echo "\n```\n\n".'#### Structure (`var_dump()`)'."\n\n```php\n";
|
||||
var_dump($oDoc);
|
||||
|
||||
echo "\n```\n\n".'#### Output (`render()`)'."\n\n```css\n";
|
||||
print $oDoc->render();
|
||||
|
||||
echo "\n```\n";
|
||||
|
||||
Reference in New Issue
Block a user