Merge branch 'release/v1.2.0'

这个提交包含在:
H. C. Kruse 2023-12-14 14:48:54 +01:00
当前提交 d3b256f305
共有 9 个文件被更改,包括 252 次插入48 次删除

38
.github/workflows/lint-check.yml vendored 普通文件
查看文件

@ -0,0 +1,38 @@
name: Lint Tests
on:
push:
branches: [ master, develop, feature/** ]
pull_request:
branches: [ master ]
jobs:
lint-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Installing PHP
uses: shivammathur/setup-php@master
with:
php-version: '8.0'
- name: Get Composer Cache Directory 2
id: composer-cache
run: |
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
id: actions-cache
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Cache PHP dependencies
uses: actions/cache@v3
id: vendor-cache
with:
path: vendor
key: ${{ runner.OS }}-build-${{ hashFiles('**/composer.lock') }}
- name: Composer install
if: steps.vendor-cache.outputs.cache-hit != 'true'
run: composer install --no-ansi --no-interaction --no-scripts --no-suggest --prefer-dist
- name: Run Test
run: composer run test

查看文件

@ -1,6 +1,6 @@
{
"name": "octfx/template-styles-extender",
"version": "1.1.8",
"version": "1.2.0",
"type": "mediawiki-extension",
"description": "Extends TemplateStyles with new CSS properties",
"homepage": "http://www.mediawiki.org/wiki/Extension:TemplateStylesExtender",
@ -13,7 +13,7 @@
}
],
"require": {
"php": ">=7.3.19",
"php": ">=8.0",
"ext-json": "*",
"composer/installers": ">=1.0.1"
},

查看文件

@ -1,6 +1,6 @@
{
"name": "TemplateStylesExtender",
"version": "1.1.8",
"version": "1.2.0",
"author": [
"[https://www.mediawiki.org/wiki/User:Octfx Octfx]"
],
@ -11,7 +11,7 @@
"requires": {
"MediaWiki": ">= 1.39.0",
"platform": {
"php": ">=7.3.19"
"php": ">=8.0"
},
"extensions": {
"TemplateStyles": ">= 1.0"
@ -48,7 +48,11 @@
},
"HookHandlers": {
"MainHooks": {
"class": "MediaWiki\\Extension\\TemplateStylesExtender\\Hooks\\MainHooks"
"class": "MediaWiki\\Extension\\TemplateStylesExtender\\Hooks\\MainHooks",
"services": [
"PermissionManager",
"UserFactory"
]
}
},
"Hooks": {

查看文件

@ -2,18 +2,45 @@
namespace MediaWiki\Extension\TemplateStylesExtender\Hooks;
use MediaWiki\EditPage\EditPage;
use MediaWiki\Extension\TemplateStyles\Hooks;
use MediaWiki\Extension\TemplateStylesExtender\TemplateStylesExtender;
use MediaWiki\Hook\EditPage__attemptSaveHook;
use MediaWiki\Hook\ParserFirstCallInitHook;
use MediaWiki\MediaWikiServices;
use MediaWiki\Permissions\PermissionManager;
use MediaWiki\Revision\SlotRecord;
use MediaWiki\User\UserFactory;
use MWException;
use Parser;
use PermissionsError;
use PPFrame;
/**
* phpcs:disable MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName
*/
class MainHooks implements ParserFirstCallInitHook, EditPage__attemptSaveHook {
/**
* @var PermissionManager
*/
private PermissionManager $manager;
/**
* @var UserFactory
*/
private UserFactory $factory;
/**
* @param PermissionManager $manager
* @param UserFactory $factory
*/
public function __construct( PermissionManager $manager, UserFactory $factory ) {
$this->manager = $manager;
$this->factory = $factory;
}
/**
* @param Parser $parser
* @throws MWException
*/
public function onParserFirstCallInit( $parser ) {
@ -21,7 +48,14 @@ class MainHooks implements ParserFirstCallInitHook, EditPage__attemptSaveHook {
}
/**
* This is a wrapper for <templatestyles> tags, that allows unscoping of css for users with 'editinterface' permissions
* This is a wrapper for <templatestyles> tags,
* that allows unscoping of css for users with 'editinterface' permissions
*
* @param string $text
* @param string[] $params
* @param Parser $parser
* @param PPFrame $frame
* @return string
* @see Hooks::handleTag()
*/
public static function handleTag( $text, $params, $parser, $frame ): string {
@ -48,7 +82,7 @@ class MainHooks implements ParserFirstCallInitHook, EditPage__attemptSaveHook {
/**
* Check if 'wrapclass' was used in the page, if so only users with 'editinterface' permissions may save the page
*
* @param $editpage_Obj
* @param EditPage $editpage_Obj
* @return true
* @throws PermissionsError
*/
@ -69,13 +103,10 @@ class MainHooks implements ParserFirstCallInitHook, EditPage__attemptSaveHook {
$permission = TemplateStylesExtender::getConfigValue( 'TemplateStylesExtenderUnscopingPermission' );
$permManager = MediaWikiServices::getInstance()->getPermissionManager();
$user = MediaWikiServices::getInstance()
->getUserFactory()
->newFromUserIdentity( $editpage_Obj->getContext()->getUser() );
$user = $this->factory->newFromUserIdentity( $editpage_Obj->getContext()->getUser() );
$userCan = $permManager->userHasRight( $user, $permission ) ||
$permManager->userCan( $permission, $user, $editpage_Obj->getTitle() );
$userCan = $this->manager->userHasRight( $user, $permission ) ||
$this->manager->userCan( $permission, $user, $editpage_Obj->getTitle() );
if ( strpos( $content->getText(), 'wrapclass' ) !== false && !$userCan ) {
throw new PermissionsError( $permission, [ 'templatestylesextender-unscope-no-permisson' ] );

查看文件

@ -27,7 +27,7 @@ use Wikimedia\CSS\Sanitizer\StylePropertySanitizer;
class PropertySanitizerHook {
/**
* @param StylePropertySanitizer $propertySanitizer
* @param StylePropertySanitizer &$propertySanitizer
* @param TemplateStylesMatcherFactory $matcherFactory
*/
public static function onSanitize( &$propertySanitizer, $matcherFactory ): void {

查看文件

@ -67,6 +67,8 @@ class StylesheetSanitizerHook {
$extended->addPointerEvents( $extender );
$extended->addScrollMarginProperties( $extender, $matcherFactory );
$extended->addAspectRatio( $extender, $matcherFactory );
$extended->addInlineBlockMarginPaddingProperties( $extender, $matcherFactory );
$extended->addInsetProperties( $extender, $matcherFactory );
$propertySanitizer->setKnownProperties( $extender->getKnownProperties() );
}

查看文件

@ -21,6 +21,7 @@ declare( strict_types=1 );
namespace MediaWiki\Extension\TemplateStylesExtender;
use MediaWiki\Extension\TemplateStylesExtender\Matcher\VarNameMatcher;
use Wikimedia\CSS\Grammar\Alternative;
use Wikimedia\CSS\Grammar\AnythingMatcher;
use Wikimedia\CSS\Grammar\BlockMatcher;
@ -53,6 +54,67 @@ class MatcherFactoryExtender extends MatcherFactory {
return $this->cache[__METHOD__];
}
/**
* CSS-color extension enabling RGBA
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color
* @return Matcher
*/
public function color()
{
if ( !isset( $this->cache[__METHOD__] ) ) {
$color = new Alternative( [
parent::color(),
new TokenMatcher( Token::T_HASH, static function ( Token $t ) {
return preg_match( '/^([0-9a-f]{4})|([0-9a-f]{8})$/i', $t->value() );
} ),
]);
$this->cache[__METHOD__] = $color;
}
return $this->cache[__METHOD__];
}
/**
* Adds `var` support to color functions
* @return Matcher|Matcher[]
*/
protected function colorFuncs() {
if ( !isset( $this->cache[__METHOD__] ) ) {
$var = new FunctionMatcher( 'var', new VarNameMatcher() );
$i = $this->integer();
$iVar = new Alternative([ $var, $i ]);
$n = $this->number();
$nVar = new Alternative([ $var, $n ]);
$p = $this->percentage();
$pVar = new Alternative([ $var, $p ]);
$this->cache[__METHOD__] = [
new FunctionMatcher( 'rgb', new Alternative( [
Quantifier::hash( $iVar, 3, 3 ),
Quantifier::hash( $pVar, 3, 3 ),
Quantifier::hash( $var, 1, 3 ),
] ) ),
new FunctionMatcher( 'rgba', new Alternative( [
new Juxtaposition( [ $iVar, $iVar, $iVar, $nVar ], true ),
new Juxtaposition( [ $pVar, $pVar, $pVar, $nVar ], true ),
Quantifier::hash( $var, 1, 4 ),
new Juxtaposition( [ Quantifier::hash( $var, 1, 3 ), $nVar ], true ),
] ) ),
new FunctionMatcher( 'hsl', new Alternative([
new Juxtaposition( [ $nVar, $pVar, $pVar ], true ),
Quantifier::hash($var, 1, 3),
]) ),
new FunctionMatcher( 'hsla', new Alternative([
new Juxtaposition( [ $nVar, $pVar, $pVar, $nVar ], true ),
Quantifier::hash($var, 1, 4),
]) ),
];
}
return $this->cache[__METHOD__];
}
/**
* This is in reality a complete copy of the parent hook with line 68 and 110 extended
* This can very easily break if there is an update upstream

查看文件

@ -27,11 +27,9 @@ use Wikimedia\CSS\Grammar\FunctionMatcher;
use Wikimedia\CSS\Grammar\KeywordMatcher;
use Wikimedia\CSS\Grammar\MatcherFactory;
use Wikimedia\CSS\Grammar\Quantifier;
use Wikimedia\CSS\Grammar\TokenMatcher;
use Wikimedia\CSS\Grammar\UnorderedGroup;
use Wikimedia\CSS\Objects\CSSObject;
use Wikimedia\CSS\Objects\Declaration;
use Wikimedia\CSS\Objects\Token;
use Wikimedia\CSS\Sanitizer\StylePropertySanitizer;
class StylePropertySanitizerExtender extends StylePropertySanitizer {
@ -42,6 +40,13 @@ class StylePropertySanitizerExtender extends StylePropertySanitizer {
private static $extendedCssSizing3 = false;
private static $extendedCss1Masking = false;
/**
* @param MatcherFactory $matcherFactory
*/
public function __construct( MatcherFactory $matcherFactory ) {
parent::__construct( new MatcherFactoryExtender() );
}
/**
* @inheritDoc
* Allow overflow-wrap: anywhere
@ -87,13 +92,6 @@ class StylePropertySanitizerExtender extends StylePropertySanitizer {
$props = parent::cssBorderBackground3( $matcherFactory );
$props['background-color'] = new Alternative( [
$matcherFactory->color(),
new TokenMatcher( Token::T_HASH, function ( Token $t ) {
return preg_match( '/^([0-9a-f]{3}|[0-9a-f]{8})$/i', $t->value() );
} ),
] );
$props['border'] = UnorderedGroup::someOf( [
new KeywordMatcher( [
'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset'
@ -103,7 +101,7 @@ class StylePropertySanitizerExtender extends StylePropertySanitizer {
] ),
new Alternative( [
$matcherFactory->color(),
new FunctionMatcher( 'var', new VarNameMatcher() ),
new FunctionMatcher( 'var', new VarNameMatcher() ),
] )
] );
@ -112,9 +110,9 @@ class StylePropertySanitizerExtender extends StylePropertySanitizer {
Quantifier::hash( UnorderedGroup::allOf( [
Quantifier::optional( new KeywordMatcher( 'inset' ) ),
Quantifier::count( $matcherFactory->length(), 2, 4 ),
Quantifier::optional(new Alternative( [
Quantifier::optional( new Alternative( [
$matcherFactory->color(),
new FunctionMatcher( 'var', new VarNameMatcher() ),
new FunctionMatcher( 'var', new VarNameMatcher() ),
] ) ),
] ) )
] );

查看文件

@ -51,36 +51,44 @@ class TemplateStylesExtender {
* @param MatcherFactory $factory
*/
public function addVarSelector( StylePropertySanitizer $propertySanitizer, MatcherFactory $factory ): void {
$anyProperty = new Alternative( [
$factory->color(),
$factory->image(),
$factory->length(),
$factory->integer(),
$factory->percentage(),
$factory->number(),
$factory->angle(),
$factory->frequency(),
$factory->resolution(),
$factory->position(),
$factory->cssSingleEasingFunction(),
$factory->comma(),
$factory->cssWideKeywords(),
new KeywordMatcher( [
'solid', 'double', 'dotted', 'dashed', 'wavy'
] )
] );
$var = new FunctionMatcher(
'var',
new Juxtaposition( [
new WhitespaceMatcher( [ 'significant' => false ] ),
new VarNameMatcher(),
new WhitespaceMatcher( [ 'significant' => false ] ),
Quantifier::optional( new Juxtaposition( [
$factory->comma(),
new WhitespaceMatcher( [ 'significant' => false ] ),
$anyProperty,
] ) ),
new WhitespaceMatcher( [ 'significant' => false ] ),
] )
);
$anyProperty = Quantifier::star(
new Alternative( [
$var,
$factory->color(),
$factory->image(),
$factory->length(),
$factory->integer(),
$factory->percentage(),
$factory->number(),
$factory->angle(),
$factory->frequency(),
$factory->resolution(),
$factory->position(),
$factory->cssSingleEasingFunction(),
$factory->comma(),
$factory->cssWideKeywords(),
new KeywordMatcher( [
'solid', 'double', 'dotted', 'dashed', 'wavy'
] )
] )
);
$anyProperty = Quantifier::star( new Alternative( [
$var,
$anyProperty,
] ) );
// Match anything*\s?[var anything|anything var]+\s?anything*(!important)?
// The problem is, that var() can be used more or less anywhere
@ -206,6 +214,67 @@ class TemplateStylesExtender {
}
}
/**
* Adds padding|margin-inline|block support
*
* @param StylePropertySanitizer $propertySanitizer
* @param MatcherFactory $factory
*/
public function addInlineBlockMarginPaddingProperties( $propertySanitizer, $factory ): void {
$auto = new KeywordMatcher( 'auto' );
$autoLengthPct = new Alternative( [ $auto, $factory->lengthPercentage() ] );
$props = [];
$props['margin-block-end'] = $autoLengthPct;
$props['margin-block-start'] = $autoLengthPct;
$props['margin-block'] = Quantifier::count( $autoLengthPct, 1, 2 );
$props['margin-inline-end'] = $autoLengthPct;
$props['margin-inline-start'] = $autoLengthPct;
$props['margin-inline'] = Quantifier::count( $autoLengthPct, 1, 2 );
$props['padding-block-end'] = $autoLengthPct;
$props['padding-block-start'] = $autoLengthPct;
$props['padding-block'] = Quantifier::count( $autoLengthPct, 1, 2 );
$props['padding-inline-end'] = $autoLengthPct;
$props['padding-inline-start'] = $autoLengthPct;
$props['padding-inline'] = Quantifier::count( $autoLengthPct, 1, 2 );
try {
$propertySanitizer->addKnownProperties( $props );
} catch ( InvalidArgumentException $e ) {
// Fail silently
}
}
/**
* Adds padding|margin-inline|block support
*
* @param StylePropertySanitizer $propertySanitizer
* @param MatcherFactory $factory
*/
public function addInsetProperties( $propertySanitizer, $factory ): void {
$auto = new KeywordMatcher( 'auto' );
$autoLengthPct = new Alternative( [ $auto, $factory->lengthPercentage() ] );
$props = [];
$props['inset'] = Quantifier::count( $autoLengthPct, 1, 4 );
$props['inset-block'] = Quantifier::count( $autoLengthPct, 1, 2 );
$props['inset-block-end'] = $autoLengthPct;
$props['inset-block-start'] = $autoLengthPct;
$props['inset-inline'] = Quantifier::count( $autoLengthPct, 1, 2 );
$props['inset-inline-end'] = $autoLengthPct;
$props['inset-inline-start'] = $autoLengthPct;
try {
$propertySanitizer->addKnownProperties( $props );
} catch ( InvalidArgumentException $e ) {
// Fail silently
}
}
/**
* Adds the pointer-events matcher
*