Merge "Hoist selectors for html and body element"

This commit is contained in:
jenkins-bot 2018-08-27 13:04:53 +00:00 committed by Gerrit Code Review
commit cbad0f06ba
3 changed files with 29 additions and 2 deletions

View file

@ -2,7 +2,7 @@
"license": "GPL-2.0-or-later", "license": "GPL-2.0-or-later",
"require": { "require": {
"cssjanus/cssjanus": "1.2.0", "cssjanus/cssjanus": "1.2.0",
"wikimedia/css-sanitizer": "~1.0.6" "wikimedia/css-sanitizer": "~2.0.0"
}, },
"require-dev": { "require-dev": {
"jakub-onderka/php-parallel-lint": "1.0.0", "jakub-onderka/php-parallel-lint": "1.0.0",

View file

@ -5,6 +5,9 @@
* @license GPL-2.0-or-later * @license GPL-2.0-or-later
*/ */
use Wikimedia\CSS\Grammar\CheckedMatcher;
use Wikimedia\CSS\Grammar\Match;
use Wikimedia\CSS\Objects\ComponentValueList;
use Wikimedia\CSS\Objects\Token; use Wikimedia\CSS\Objects\Token;
use Wikimedia\CSS\Sanitizer\FontFeatureValuesAtRuleSanitizer; use Wikimedia\CSS\Sanitizer\FontFeatureValuesAtRuleSanitizer;
use Wikimedia\CSS\Sanitizer\KeyframesAtRuleSanitizer; use Wikimedia\CSS\Sanitizer\KeyframesAtRuleSanitizer;
@ -61,6 +64,20 @@ class TemplateStylesHooks {
) ); ) );
Hooks::run( 'TemplateStylesPropertySanitizer', [ &$propertySanitizer, $matcherFactory ] ); Hooks::run( 'TemplateStylesPropertySanitizer', [ &$propertySanitizer, $matcherFactory ] );
$htmlOrBodySimpleSelectorSeqMatcher = new CheckedMatcher(
$matcherFactory->cssSimpleSelectorSeq(),
function ( ComponentValueList $values, Match $match, array $options ) {
foreach ( $match->getCapturedMatches() as $m ) {
if ( $m->getName() !== 'element' ) {
continue;
}
$str = (string)$m;
return $str === 'html' || $str === 'body';
}
return false;
}
);
$atRuleBlacklist = array_flip( $config->get( 'TemplateStylesAtRuleBlacklist' ) ); $atRuleBlacklist = array_flip( $config->get( 'TemplateStylesAtRuleBlacklist' ) );
$ruleSanitizers = [ $ruleSanitizers = [
'styles' => new StyleRuleSanitizer( 'styles' => new StyleRuleSanitizer(
@ -70,8 +87,8 @@ class TemplateStylesHooks {
'prependSelectors' => [ 'prependSelectors' => [
new Token( Token::T_DELIM, '.' ), new Token( Token::T_DELIM, '.' ),
new Token( Token::T_IDENT, $class ), new Token( Token::T_IDENT, $class ),
new Token( Token::T_WHITESPACE ),
], ],
'hoistableComponentMatcher' => $htmlOrBodySimpleSelectorSeqMatcher,
] ]
), ),
'@font-face' => new TemplateStylesFontFaceAtRuleSanitizer( $matcherFactory ), '@font-face' => new TemplateStylesFontFaceAtRuleSanitizer( $matcherFactory ),

View file

@ -24,6 +24,9 @@ class TemplateStylesHooksTest extends MediaWikiLangTestCase {
$this->addPage( 'nonsanitized.css', '.foo { color: red; }', CONTENT_MODEL_CSS ); $this->addPage( 'nonsanitized.css', '.foo { color: red; }', CONTENT_MODEL_CSS );
$this->addPage( 'styles1.css', '.foo { color: blue; }', 'sanitized-css' ); $this->addPage( 'styles1.css', '.foo { color: blue; }', 'sanitized-css' );
$this->addPage( 'styles2.css', '.bar { color: green; }', 'sanitized-css' ); $this->addPage( 'styles2.css', '.bar { color: green; }', 'sanitized-css' );
$this->addPage(
'styles3.css', 'html.no-js body.skin-minerva .bar { color: yellow; }', 'sanitized-css'
);
} }
/** /**
@ -277,6 +280,13 @@ class TemplateStylesHooksTest extends MediaWikiLangTestCase {
"<div class=\"templatestyles-test\"><style data-mw-deduplicate=\"TemplateStyles:8fd14043c1cce91e8b9d1487a9d17d8d9ae43890/templatestyles-test\">/*\nErrors processing stylesheet [[:Template:Test replacement]] (rev ):\n• Unrecognized or unsupported property at line 1 character 22.\n*/\n.templatestyles-test .baz{color:orange}</style>\n</div>", "<div class=\"templatestyles-test\"><style data-mw-deduplicate=\"TemplateStyles:8fd14043c1cce91e8b9d1487a9d17d8d9ae43890/templatestyles-test\">/*\nErrors processing stylesheet [[:Template:Test replacement]] (rev ):\n• Unrecognized or unsupported property at line 1 character 22.\n*/\n.templatestyles-test .baz{color:orange}</style>\n</div>",
// @codingStandardsIgnoreEnd // @codingStandardsIgnoreEnd
], ],
'Hoistable selectors are hoisted' => [
$popt, [],
'<templatestyles src="TemplateStyles test/styles3.css" />',
// @codingStandardsIgnoreStart Ignore Generic.Files.LineLength.TooLong
"<div class=\"templatestyles-test\"><style data-mw-deduplicate=\"TemplateStyles:r{{REV:styles3.css}}/templatestyles-test\">html.no-js body.skin-minerva .templatestyles-test .bar{color:yellow}</style>\n</div>",
// @codingStandardsIgnoreEnd
],
'Still prefixed despite no wrapper' => [ 'Still prefixed despite no wrapper' => [
$popt2, [ 'unwrap' => true ], $popt2, [ 'unwrap' => true ],
'<templatestyles src="TemplateStyles test/styles1.css" />', '<templatestyles src="TemplateStyles test/styles1.css" />',