diff --git a/lib/adminlib.php b/lib/adminlib.php index d8cbf40b03a..e9fcd077923 100644 --- a/lib/adminlib.php +++ b/lib/adminlib.php @@ -9081,6 +9081,7 @@ class admin_setting_configcolourpicker extends admin_setting { $context = (object) [ 'id' => $this->get_id(), 'name' => $this->get_full_name(), + 'value' => $data, 'icon' => $icon->export_for_template($OUTPUT), 'haspreviewconfig' => !empty($this->previewconfig), 'forceltr' => $this->get_force_ltr() diff --git a/lib/classes/scss.php b/lib/classes/scss.php index e60b8e0a8fe..5a5e2abbd21 100644 --- a/lib/classes/scss.php +++ b/lib/classes/scss.php @@ -35,6 +35,8 @@ class core_scss extends \Leafo\ScssPhp\Compiler { /** @var string The path to the SCSS file. */ protected $scssfile; + /** @var array Bits of SCSS content to prepend. */ + protected $scssprepend = array(); /** @var array Bits of SCSS content. */ protected $scsscontent = array(); @@ -58,6 +60,16 @@ class core_scss extends \Leafo\ScssPhp\Compiler { $this->scsscontent[] = $scss; } + /** + * Prepend raw SCSS to what's to compile. + * + * @param string $scss SCSS code. + * @return void + */ + public function prepend_raw_scss($scss) { + $this->scssprepend[] = $scss; + } + /** * Set the file to compile from. * @@ -78,7 +90,7 @@ class core_scss extends \Leafo\ScssPhp\Compiler { * @return string */ public function to_css() { - $content = ''; + $content = implode(';', $this->scssprepend); if (!empty($this->scssfile)) { $content .= file_get_contents($this->scssfile); } diff --git a/lib/outputlib.php b/lib/outputlib.php index cc580b063d2..726e99ff0ab 100644 --- a/lib/outputlib.php +++ b/lib/outputlib.php @@ -444,10 +444,10 @@ class theme_config { public $lessvariablescallback = null; /** - * The name of the function to call to get extra SCSS variables. + * The name of the function to call to get SCSS to prepend. * @var string */ - public $scssvariablescallback = null; + public $prescsscallback = null; /** * Sets the render method that should be used for rendering custom block regions by scripts such as my/index.php @@ -528,7 +528,7 @@ class theme_config { 'rendererfactory', 'csspostprocess', 'editor_sheets', 'rarrow', 'larrow', 'uarrow', 'darrow', 'hidefromselector', 'doctype', 'yuicssmodules', 'blockrtlmanipulations', 'lessfile', 'extralesscallback', 'lessvariablescallback', 'blockrendermethod', - 'scssfile', 'extrascsscallback', 'scssvariablescallback', 'csstreepostprocessor'); + 'scssfile', 'extrascsscallback', 'prescsscallback', 'csstreepostprocessor'); foreach ($config as $key=>$value) { if (in_array($key, $configurable)) { @@ -1190,9 +1190,9 @@ class theme_config { // Set-up the compiler. $compiler = new core_scss(); + $compiler->prepend_raw_scss($this->get_pre_scss_code()); $compiler->set_file($themescssfile); $compiler->append_raw_scss($this->get_extra_scss_code()); - $compiler->add_variables($this->get_scss_variables()); try { // Compile! @@ -1243,39 +1243,6 @@ class theme_config { return $variables; } - /** - * Return extra SCSS variables to use when compiling. - * - * @return array Where keys are the variable names, and the values are the value. - */ - protected function get_scss_variables() { - $variables = array(); - - // Getting all the candidate functions. - $candidates = array(); - foreach ($this->parent_configs as $parent_config) { - if (!isset($parent_config->scssvariablescallback)) { - continue; - } - $candidates[] = $parent_config->scssvariablescallback; - } - $candidates[] = $this->scssvariablescallback; - - // Calling the functions. - foreach ($candidates as $function) { - if (function_exists($function)) { - $vars = $function($this); - if (!is_array($vars)) { - debugging('Callback ' . $function . ' did not return an array() as expected', DEBUG_DEVELOPER); - continue; - } - $variables = array_merge($variables, $vars); - } - } - - return $variables; - } - /** * Return extra LESS code to add when compiling. * @@ -1340,6 +1307,36 @@ class theme_config { return $content; } + /** + * SCSS code to prepend when compiling. + * + * This is intended to be used by themes to inject SCSS code before it gets compiled. + * + * @return string The SCSS code to inject. + */ + protected function get_pre_scss_code() { + $content = ''; + + // Getting all the candidate functions. + $candidates = array(); + foreach ($this->parent_configs as $parent_config) { + if (!isset($parent_config->prescsscallback)) { + continue; + } + $candidates[] = $parent_config->prescsscallback; + } + $candidates[] = $this->prescsscallback; + + // Calling the functions. + foreach ($candidates as $function) { + if (function_exists($function)) { + $content .= "\n/** Pre-SCSS from $function **/\n" . $function($this) . "\n"; + } + } + + return $content; + } + /** * Generate a URL to the file that serves theme JavaScript files. * diff --git a/theme/boost/classes/admin_setting_scss_variables.php b/theme/boost/classes/admin_setting_scss_variables.php deleted file mode 100644 index 6e043fa096d..00000000000 --- a/theme/boost/classes/admin_setting_scss_variables.php +++ /dev/null @@ -1,57 +0,0 @@ -. - -/** - * Admin setting for SCSS variables. - * - * @package theme_boost - * @copyright 2016 Frédéric Massart - FMCorz.net - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Admin setting for SCSS variables class. - * - * @package theme_boost - * @copyright 2016 Frédéric Massart - FMCorz.net - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class theme_boost_admin_setting_scss_variables extends admin_setting_configtextarea { - - /** - * Validate data before storage. - * - * @param string $data The data. - * @return mixed True if validated, else an error string. - */ - public function validate($data) { - if (empty($data)) { - return true; - } - - try { - theme_boost_parse_scss_variables($data, false); - } catch (moodle_exception $e) { - return $e->getMessage(); - } - - return true; - } - -} - diff --git a/theme/boost/config.php b/theme/boost/config.php index f60f1f4e769..f52949d803f 100644 --- a/theme/boost/config.php +++ b/theme/boost/config.php @@ -146,6 +146,6 @@ $THEME->parents = []; $THEME->enable_dock = false; $THEME->csstreepostprocessor = 'theme_boost_css_tree_post_processor'; $THEME->extrascsscallback = 'theme_boost_get_extra_scss'; -$THEME->scssvariablescallback = 'theme_boost_get_scss_variables'; +$THEME->prescsscallback = 'theme_boost_get_pre_scss'; $THEME->yuicssmodules = array(); $THEME->rendererfactory = 'theme_overridden_renderer_factory'; diff --git a/theme/boost/lang/en/theme_boost.php b/theme/boost/lang/en/theme_boost.php index 7fa233227b3..0750bfeb1a3 100644 --- a/theme/boost/lang/en/theme_boost.php +++ b/theme/boost/lang/en/theme_boost.php @@ -30,7 +30,6 @@ $string['brandcolor_desc'] = 'The accent colour.'; $string['choosereadme'] = 'Boost is a modern highly customizable theme. This theme is intended to be used directly, or used as a parent theme when creating new themes utilising Boostrap 4.'; $string['currentinparentheses'] = '(current)'; $string['configtitle'] = 'Boost'; -$string['errorparsingscssvariables'] = 'There was an error parsing the variable at line {$a}, please double check the syntax.'; $string['generalsettings'] = 'General settings'; $string['pluginname'] = 'Boost'; $string['preset'] = 'Theme preset'; @@ -41,8 +40,8 @@ $string['presetpaper'] = 'Paper'; $string['presetplain'] = 'Plain'; $string['presetreadable'] = 'Readable'; $string['rawscss'] = 'Raw SCSS'; -$string['rawscss_desc'] = 'Use this field to provide SCSS code which will be injected at the end of the the stylesheet.'; +$string['rawscss_desc'] = 'Use this field to provide SCSS code which will be injected at the end of the stylesheet.'; +$string['rawscsspre'] = 'Raw initial SCSS'; +$string['rawscsspre_desc'] = 'In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.'; $string['region-side-post'] = 'Right'; $string['region-side-pre'] = 'Left'; -$string['scssvariables'] = 'SCSS variables'; -$string['scssvariables_desc'] = 'Use this field to set your own SCSS variable values. Define one variable per line. Syntax: $my-color: red;.'; diff --git a/theme/boost/lib.php b/theme/boost/lib.php index 72776d5b820..6f18143bb3f 100644 --- a/theme/boost/lib.php +++ b/theme/boost/lib.php @@ -57,73 +57,33 @@ function theme_boost_get_extra_scss($theme) { } /** - * Get additional SCSS variables. + * Get SCSS to prepend. * * @param theme_config $theme The theme config object. * @return array */ -function theme_boost_get_scss_variables($theme) { - $variables = []; +function theme_boost_get_pre_scss($theme) { + $scss = ''; $configurable = [ // Config key => [variableName, ...]. 'brandcolor' => ['brand-primary'], ]; + // Prepend variables first. foreach ($configurable as $configkey => $targets) { $value = $theme->settings->{$configkey}; if (empty($value)) { continue; } - array_map(function($target) use (&$variables, $value) { - $variables[$target] = $value; + array_map(function($target) use (&$scss, $value) { + $scss .= '$' . $target . ': ' . $value . ";\n"; }, (array) $targets); } - if (!empty($theme->settings->scss_variables)) { - $variables = array_merge($variables, theme_boost_parse_scss_variables($theme->settings->scss_variables)); + // Prepend pre-scss. + if (!empty($theme->settings->scsspre)) { + $scss .= $theme->settings->scsspre; } - return $variables; -} - -/** - * Parse a string into SCSS variables. - * - * - One variable definition per line, - * - The variable name is separated from the value by a colon, - * - The dollar sign is optional, - * - The trailing semi-colon is optional, - * - CSS comments (starting with //) are accepted - * - Variables names can only contain letters, numbers, hyphens and underscores. - * - * @param string $data The string to parse from. - * @param bool $lenient When non lenient, an exception will be thrown when a line cannot be parsed. - * @return array - */ -function theme_boost_parse_scss_variables($data, $lenient = true) { - $variables = []; - $lines = explode("\n", $data); - $i = 0; - - foreach ($lines as $line) { - $i++; - if (preg_match('@^\s*//@', $line)) { - continue; - } - - $parts = explode(':', trim($line)); - $variable = ltrim($parts[0], '$ '); - $value = rtrim(ltrim(isset($parts[1]) ? $parts[1] : ''), "; "); - - if (empty($variable) || !preg_match('/^[a-z0-9_-]+$/i', $variable) || (empty($value) && !is_numeric($value))) { - if ($lenient) { - continue; - } - throw new moodle_exception('errorparsingscssvariables', 'theme_boost', null, $i); - } - - $variables[$variable] = $value; - } - - return $variables; + return $scss; } diff --git a/theme/boost/settings.php b/theme/boost/settings.php index e4b5eb3a711..505db9b5471 100644 --- a/theme/boost/settings.php +++ b/theme/boost/settings.php @@ -58,13 +58,13 @@ if ($ADMIN->fulltree) { // Advanced settings. $page = new admin_settingpage('theme_boost_advanced', get_string('advancedsettings', 'theme_boost')); - // Raw SCSS for before the content. - $setting = new theme_boost_admin_setting_scss_variables('theme_boost/scss_variables', - get_string('scssvariables', 'theme_boost'), get_string('scssvariables_desc', 'theme_boost'), '', PARAM_RAW); + // Raw SCSS to include before the content. + $setting = new admin_setting_configtextarea('theme_boost/scsspre', + get_string('rawscsspre', 'theme_boost'), get_string('rawscsspre_desc', 'theme_boost'), '', PARAM_RAW); $setting->set_updatedcallback('theme_reset_all_caches'); $page->add($setting); - // Raw SCSS for after the content. + // Raw SCSS to include after the content. $setting = new admin_setting_configtextarea('theme_boost/scss', get_string('rawscss', 'theme_boost'), get_string('rawscss_desc', 'theme_boost'), '', PARAM_RAW); $setting->set_updatedcallback('theme_reset_all_caches'); diff --git a/theme/upgrade.txt b/theme/upgrade.txt index ed20d7ea4e8..e8848cbb391 100644 --- a/theme/upgrade.txt +++ b/theme/upgrade.txt @@ -17,6 +17,8 @@ Removed themes: * Bootstrap 4 was added as part of a the new theme 'boost'. * Themes can now automatically compile SCSS on the fly. This works the same way as it does compiling LESS on the fly, effecitvely adding $THEME->scssfile to your config. +* Two new callbacks allow themes to inject SCSS code before and after the content provided + by the SCSS file $THEME->scssfile. See $THEME->prescsscallback and $THEME->extrascsscallback. * Using .dir-rtl for RTL styling is deprecated and should not be used any more. From now the styles are automatically flipped when the language is right-to-left. However, as this is not always perfect, you can define exceptions. Please refer to the documentation