Usage
PHP
nebula()->render_scss($child)
Parameters
$child
(Optional) (Boolean) If checking child theme directory
Default: false
Additional Notes
This function is typically called automatically as needed and generally does not need to be called manually.
Source File
Located in /libs/Utilities/Sass.php on line 174.
4 Hooks
Find these filters and actions in the source code below to hook into them. Use do_action() and add_filter() in your functions file or plugin.
Filters
"pre_nebula_render_scss""nebula_scss_variables"
Need a new filter hook? Request one here.
Actions
"nebula_before_sass_compile""qm/error"
Need a new action hook? Request one here.
Note: This function contains 4 to-do comments.
PHP
public function render_scss($location_name=false, $location_paths=false, $force_all=false){ $override = apply_filters('pre_nebula_render_scss', null, $location_name, $location_paths, $force_all); if ( isset($override) ){return;} global $sass_errors; if ( $this->get_option('scss') && !empty($location_name) && !empty($location_paths) ){ $this->timer('Sass (' . $location_name . ')', 'start', 'Sass'); //Require SCSSPHP require_once get_template_directory() . '/inc/vendor/scssphp/scss.inc.php'; //Run the autoloader. SCSSPHP is a compiler for SCSS 3.x $this->scss = new \ScssPhp\ScssPhp\Compiler(); //Register import directories if ( !empty($location_paths['imports']) ){ if ( !is_array($location_paths['imports']) ){ $location_paths['imports'] = array($location_paths['imports']); //Convert to an array if passes as a string } foreach ( $location_paths['imports'] as $imports_directory ){ $this->scss->addImportPath($imports_directory); } } //Set compiling options $this->scss->setOutputStyle(\ScssPhp\ScssPhp\OutputStyle::COMPRESSED); //Minify CSS (while leaving "/*!" comments for WordPress). //Source Maps $this->scss->setSourceMap(1); //0 = No .map, 1 = Inline .map, 2 = Output .map file $this->scss->setSourceMapOptions(array( 'sourceMapBasepath' => ABSPATH, //Difference between file & URL locations, removed from all source paths in .map 'sourceRoot' => '/', //Added to source path locations if needed )); //Variables $nebula_scss_variables = array( 'parent_partials_directory' => \ScssPhp\ScssPhp\ValueConverter::fromPhp(get_template_directory() . '/assets/scss/partials/'), //There must be a better way to call fromPhp() here... 'child_partials_directory' => \ScssPhp\ScssPhp\ValueConverter::fromPhp(get_stylesheet_directory() . '/assets/scss/partials/'), //There must be a better way to call fromPhp() here... 'template_directory' => \ScssPhp\ScssPhp\ValueConverter::fromPhp(get_template_directory_uri()), //There must be a better way to call fromPhp() here... 'stylesheet_directory' => \ScssPhp\ScssPhp\ValueConverter::fromPhp(get_stylesheet_directory_uri()), //There must be a better way to call fromPhp() here... 'this_directory' => \ScssPhp\ScssPhp\ValueConverter::fromPhp($location_paths['uri']), //There must be a better way to call fromPhp() here... 'primary_color' => \ScssPhp\ScssPhp\ValueConverter::parseValue($this->get_color('primary_color', false, '#0098d7')), //There must be a better way to call parseValue() here... 'secondary_color' => \ScssPhp\ScssPhp\ValueConverter::parseValue($this->get_color('secondary_color', false, '#95d600')), //There must be a better way to call parseValue() here... 'background_color' => \ScssPhp\ScssPhp\ValueConverter::parseValue($this->get_color('background_color', false, '#f6f6f6')), //There must be a better way to call parseValue() here... ); $all_scss_variables = apply_filters('nebula_scss_variables', $nebula_scss_variables); $this->scss->addVariables($nebula_scss_variables); //Imports/Partials (find the last modified time) $latest_import = 0; foreach ( glob($imports_directory . '*') as $import_file ){ if ( filemtime($import_file) > $latest_import ){ $latest_import = filemtime($import_file); if ( $latest_import > $this->latest_scss_mtime ){ $this->latest_scss_mtime = $latest_import; } } } $this->add_custom_scssphp_functions($this->scss); //Add custom PHP functions that can be used in Sass do_action('nebula_before_sass_compile', $location_paths); //Allow modification of files before looping through to compile Sass //Compile each SCSS file foreach ( glob($location_paths['core'] . '*.scss') as $scss_file ){ //@TODO "Nebula" 0: Change to glob_r() but will need to create subdirectories if they don't exist. $scss_file_path_info = pathinfo($scss_file); $debug_name = str_replace(WP_CONTENT_DIR, '', $scss_file_path_info['dirname']) . '/' . $scss_file_path_info['basename']; $this->timer('Sass File (' . $debug_name . ')'); //Skip file conditions (only if not forcing all) if ( empty($force_all) ){ //@todo "Nebula" 0: Add hook here so other functions/plugins can add stipulations of when to skip files. Maybe an array instead? $is_admin_file = (!$this->is_admin_page() && !$this->is_login_page()) && in_array($scss_file_path_info['filename'], array('login', 'admin', 'tinymce')); //If viewing front-end, skip WP admin files. if ( $is_admin_file ){ $this->timer('Sass File (' . $debug_name . ')', 'end'); continue; } } //If file exists, and has .scss extension, and doesn't begin with "_". if ( is_file($scss_file) && $scss_file_path_info['extension'] === 'scss' && $scss_file_path_info['filename'][0] !== '_' ){ //Determine the .css output filepath $output_directory = $location_paths['output']; //Default to the output directory if ( ($location_name == 'parent' || $location_name == 'child') ){ if ( $scss_file_path_info['filename'] === 'style' ){ $output_directory = $location_paths['directory'] . '/'; //Root directory for theme style.css } } $css_filepath = $output_directory . $scss_file_path_info['filename'] . '.css'; wp_mkdir_p($location_paths['output']); //Create the output directory (in case it doesn't exist already) //Update the last SCSS file modification time (if later than the latest yet) if ( filemtime($scss_file) > $this->latest_scss_mtime ){ $this->latest_scss_mtime = filemtime($scss_file); } //If style.css has been edited after style.scss, save backup but continue compiling SCSS if ( (is_child_theme() && $location_name !== 'parent' ) && ($scss_file_path_info['filename'] === 'style' && file_exists($css_filepath) && $this->get_data('scss_last_processed') != '0' && $this->get_data('scss_last_processed')-filemtime($css_filepath) < -30) ){ copy($css_filepath, $css_filepath . '.bak'); //Backup the style.css file to style.css.bak if ( $this->is_dev() || current_user_can('manage_options') ){ global $scss_debug_ref; $scss_debug_ref = $location_name . ':'; $scss_debug_ref .= ($this->get_data('scss_last_processed')-filemtime($css_filepath)); add_action('wp_head', array($this, 'scss_console_warning')); //Call the console error note } } //If .css file doesn't exist, or is older than .scss file (or any partial), or is debug mode, or forced if ( !file_exists($css_filepath) || filemtime($scss_file) > filemtime($css_filepath) || $latest_import > filemtime($css_filepath) || $this->is_debug() || $force_all ){ ini_set('memory_limit', '512M'); //Increase memory limit for this script. //@todo Nebula 0: Remove this when possible... WP_Filesystem(); global $wp_filesystem; $existing_css_contents = ( file_exists($css_filepath) )? $wp_filesystem->get_contents($css_filepath) : ''; //If the correlating .css file doesn't contain a comment to prevent overwriting if ( !strpos(strtolower($existing_css_contents), 'scss disabled') ){ //@todo "Nebula" 0: Update strpos() to str_contains() in PHP8 $this_scss_contents = $wp_filesystem->get_contents($scss_file); //Copy SCSS file contents //Catch fatal compilation errors when PHP v7.0+ to provide additional information without crashing try { $compiled_css = $this->scss->compileString($this_scss_contents, $scss_file)->getCss(); //Compile the SCSS $this->was_sass_processed = true; $this->sass_files_processed++; } catch (\Throwable $error){ $unprotected_array = (array) $error; $prefix = chr(0) . '*' . chr(0); $sass_errors[] = array( 'file' => $scss_file, 'message' => $unprotected_array[$prefix . 'message'] ); do_action('qm/error', $error); continue; //Skip the file that contains errors } $enhanced_css = $this->scss_post_compile($compiled_css); //Compile server-side variables into SCSS $wp_filesystem->put_contents($css_filepath, $enhanced_css); //Save the rendered CSS. $this->update_data('scss_last_processed', time()); } } } $this->timer('Sass File (' . $debug_name . ')', 'end'); } $this->timer('Sass (' . $location_name . ')', 'end'); } return $this->was_sass_processed; }
Override
To override this PHP function, use this hook in your child theme or plugin ("my_custom" can be changed):
PHP
add_filter('pre_nebula_render_scss', 'my_custom_render_scss', 10, 2); //The last integer must be 1 more than the actual parameters function my_custom_render_scss($null, $child){ //$null is required, but can be ignored //Write your own code here return true; //Return true to prevent the original function from running afterwords }
You can completely disable this PHP function with a single line actions:
PHP
add_filter('pre_nebula_render_scss', '__return_false');