feat: extender to add custom less variables (#3530)

This commit is contained in:
David Wheatley 2022-07-14 13:04:38 +01:00 committed by GitHub
parent 819602520a
commit bf6f63cfe1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 1 deletions

View File

@ -19,6 +19,7 @@ class Theme implements ExtenderInterface
private $lessImportOverrides = [];
private $fileSourceOverrides = [];
private $customFunctions = [];
private $lessVariables = [];
/**
* This can be used to override LESS files that are imported within the code.
@ -100,12 +101,51 @@ class Theme implements ExtenderInterface
return $this;
}
/**
* Defines a new Less variable to be accessible in all Less files.
*
* If you want to expose a setting from your database to Less, you should use
* the `registerLessConfigVar` extender from `Extend\Settings` instead.
*
* Please note the value returned from the callable will be inserted directly
* into the Less source. If it is unsafe in some way (e.g., contains a
* semi-colon), this will result in potential security issues with your
* stylesheet.
*
* Likewise, if you need your variable to be a string, you should surround it
* with quotes yourself.
*
* ```php
* (new Extend\Theme())
* ->addCustomLessVariable('my-extension__asset_path', function () {
* $url = resolve(UrlGenerator::class);
* $assetUrl = $url->to('forum')->base().'/assets/extensions/my-extension/my-asset.jpg';
* return "\"$assetUrl\"";
* })
* ```
*
* @param string $variableName Name of the variable identifier.
* @param callable $value The PHP function to run, which returns the value for the variable.
*
* @return self
*/
public function addCustomLessVariable(string $variableName, callable $value): self
{
$this->lessVariables[$variableName] = $value;
return $this;
}
public function extend(Container $container, Extension $extension = null)
{
$container->extend('flarum.frontend.custom_less_functions', function (array $customFunctions) {
return array_merge($customFunctions, $this->customFunctions);
});
$container->extend('flarum.less.custom_variables', function (array $lessVariables) {
return array_merge($this->lessVariables, $lessVariables);
});
$container->extend('flarum.assets.factory', function (callable $factory) {
return function (...$args) use ($factory) {
/** @var Assets $assets */

View File

@ -156,6 +156,13 @@ class FrontendServiceProvider extends AbstractServiceProvider
],
];
});
$this->container->singleton(
'flarum.less.custom_variables',
function (Container $container) {
return [];
}
);
}
/**
@ -184,9 +191,11 @@ class FrontendServiceProvider extends AbstractServiceProvider
{
$sources->addString(function () {
$vars = $this->container->make('flarum.less.config');
$extDefinedVars = $this->container->make('flarum.less.custom_variables');
$settings = $this->container->make(SettingsRepositoryInterface::class);
return array_reduce(array_keys($vars), function ($string, $name) use ($vars, $settings) {
$customLess = array_reduce(array_keys($vars), function ($string, $name) use ($vars, $settings) {
$var = $vars[$name];
$value = $settings->get($var['key'], $var['default'] ?? null);
@ -196,6 +205,12 @@ class FrontendServiceProvider extends AbstractServiceProvider
return $string."@$name: {$value};";
}, '');
foreach ($extDefinedVars as $name => $value) {
$customLess .= "@$name: {$value()};";
}
return $customLess;
});
}
}

View File

@ -0,0 +1,3 @@
.dummy_var_test {
--x: @doesnt-exist;
}

View File

@ -132,4 +132,28 @@ class ThemeTest extends TestCase
$this->assertStringContainsString('.dummy_func_test{color:green}', $contents);
$this->assertStringContainsString('.dummy_func_test2{--x:1000;--y:false}', $contents);
}
/**
* @test
*/
public function theme_extender_can_add_custom_variable()
{
$this->extend(
(new Extend\Frontend('forum'))
->css(__DIR__.'/../../fixtures/less/custom_variable.less'),
(new Extend\Theme)
->addCustomLessVariable('doesnt-exist', function () {
return 'it does';
})
);
$response = $this->send($this->request('GET', '/'));
$this->assertEquals(200, $response->getStatusCode());
$cssFilePath = $this->app()->getContainer()->make('filesystem')->disk('flarum-assets')->path('forum.css');
$contents = file_get_contents($cssFilePath);
$this->assertStringContainsString('.dummy_var_test{--x:it does}', $contents);
}
}