|
|
há 2 semanas atrás | |
|---|---|---|
| .. | ||
| src | há 2 semanas atrás | |
| CHANGELOG.md | há 2 semanas atrás | |
| LICENSE | há 2 semanas atrás | |
| README.md | há 2 semanas atrás | |
| composer.json | há 2 semanas atrás | |
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.
composer require sabberworm/php-css-parser
To use the CSS Parser, create a new instance. The constructor takes the following form:
new \Sabberworm\CSS\Parser($css);
To read a file, for example, you’d do the following:
$parser = new \Sabberworm\CSS\Parser(file_get_contents('somefile.css'));
$cssDocument = $parser->parse();
The resulting CSS document structure can be manipulated prior to being output.
The charset option will only be used if the CSS file does not contain an @charset declaration. 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.
$settings = \Sabberworm\CSS\Settings::create()
->withDefaultCharset('windows-1252');
$parser = new \Sabberworm\CSS\Parser($css, $settings);
To have the parser throw an exception when encountering invalid/unknown constructs (as opposed to trying to ignore them and carry on parsing), supply a thusly configured \Sabberworm\CSS\Settings object:
$parser = new \Sabberworm\CSS\Parser(
file_get_contents('somefile.css'),
\Sabberworm\CSS\Settings::create()->beStrict()
);
Note that this will also disable a workaround for parsing the unquoted variant of the legacy IE-specific filter rule.
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 using this with input you have no control over as it’s not thoroughly covered by test cases.
$settings = \Sabberworm\CSS\Settings::create()->withMultibyteSupport(false);
$parser = new \Sabberworm\CSS\Parser($css, $settings);
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 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.
To access the items stored in a CSSList – like the document you got back when calling $parser->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 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 for generic at-rules which are not covered by specific classes, i.e., not @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 CSSLists (and Imports as well as a Charset), while a RuleSet can only contain Rules.
If you want to manipulate a RuleSet, use the methods addRule(Rule $rule), getRules() and removeRule($rule) (which accepts either a Rule or a rule name; optionally suffixed by a dash to remove all related rules).
Rules just have a string key (the rule) and a 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 Values, separated by some separation character (mostly ,, whitespace, or /).
There are two types of ValueLists:
RuleValueList – The default type, used to represent all multivalued 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);.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 the selectors are. Aliased as getAllSelectors().getAllRuleSets() – does what it says; no matter how deeply nested the rule sets are.getAllValues() – finds all Value objects inside Rules.selectorsWithElement($sId/Class/TagName), attributesOfType($type), removeAttributesOfType($type))Color instead of an anonymous string literal)Parser to prepend an ID to all selectors$myId = "#my_id";
$parser = new \Sabberworm\CSS\Parser($css);
$cssDocument = $parser->parse();
foreach ($cssDocument->getAllDeclarationBlocks() as $block) {
foreach ($block->getSelectors() as $selector) {
// Loop over all selector parts (the comma-separated strings in a
// selector) and prepend the ID.
$selector->setSelector($myId.' '.$selector->getSelector());
}
}
$parser = new \Sabberworm\CSS\Parser($css);
$cssDocument = $parser->parse();
foreach ($cssDocument->getAllValues() as $value) {
if ($value instanceof CSSSize && !$value->isRelative()) {
$value->setSize($value->getSize() / 2);
}
}
$parser = new \Sabberworm\CSS\Parser($css);
$cssDocument = $parser->parse();
foreach($cssDocument->getAllRuleSets() as $oRuleSet) {
// 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('font-');
$oRuleSet->removeRule('cursor');
}
To output the entire CSS document into a variable, just use ->render():
$parser = new \Sabberworm\CSS\Parser(file_get_contents('somefile.css'));
$cssDocument = $parser->parse();
print $cssDocument->render();
If you want to format the output, pass an instance of type \Sabberworm\CSS\OutputFormat:
$format = \Sabberworm\CSS\OutputFormat::create()
->indentWithSpaces(4)->setSpaceBetweenRules("\n");
print $cssDocument->render($format);
Or use one of the predefined formats:
print $cssDocument->render(Sabberworm\CSS\OutputFormat::createPretty());
print $cssDocument->render(Sabberworm\CSS\OutputFormat::createCompact());
To see what you can do with output formatting, look at the tests in tests/OutputFormatTest.php.
@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; }
}
var_dump())render())@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;}}
#header {
margin: 10px 2em 1cm 2%;
font-family: Verdana, Helvetica, "Gill Sans", sans-serif;
color: red !important;
}
var_dump())render())#header {margin: 10px 2em 1cm 2%;font-family: Verdana,Helvetica,"Gill Sans",sans-serif;color: red !important;}
calc, grid lines, and various bugfixes.CSSList->remove() inspiration.0.9.0 tag.composer install to install phpunit and use ./vendor/bin/phpunit.