function test_Mixins() { foreach ($this->load_files('Mixins') as $item) { $out = str_replace('.css', '_out.css', $item); $original = file_get_contents($item); $expected = file_get_contents($out); $css = Mixins::parse($original); $css = Formatter::minify($css); $expected = Formatter::minify($expected); $this->assertEqual($expected, $css); } }
/** * The main processing function called by Scaffold. MUST return $css! * * @author Anthony Short * @return $css string */ public static function parse() { global $bases; # This will store our nicely formated bases array # This lets us loop through all the of +mixins and just # pull in the properties of that mixin and then parse it individually # based on the parameters $bases = array(); # Finds any selectors starting with =mixin-name if ($found = CSS::find_selectors('\\=(?P<name>[0-9a-zA-Z_-]*)(\\((?P<args>.*?)\\))?', 5)) { # Just to make life a little easier $full_base = $found[0]; $base_names = $found['name']; $base_args = $found['args']; $base_props = $found['properties']; # Clean up memory unset($found); # Puts the mixin bases into a more suitable array foreach ($base_names as $key => $value) { $bases[$value]['properties'] = $base_props[$key]; # If there are mixin arguments, add them $bases[$value]['params'] = $base_args[$key] != "" ? explode(',', $base_args[$key]) : array(); } # Store this away for debugging self::$mixins = $bases; # Remove all of the mixin bases CSS::remove($full_base); # Clean up memory unset($full_base, $base_names, $base_args, $base_props); # Find the mixins if ($mixins = self::find_mixins(CSS::$css)) { # Loop through each of the found +mixins foreach ($mixins[2] as $mixin_key => $mixin_name) { CSS::replace($mixins[0][$mixin_key], self::build_mixins($mixin_key, $mixins)); } # Remove all of the +mixins (if they still exist) CSS::replace($mixins[0], ''); } # Clean up unset($bases, $mixins); } }
/** * Extracts the mixin bases * * @param $param * @return return type */ public static function extract_bases() { # Finds any selectors starting with =mixin-name if ($found = Scaffold::$css->find_selectors('\\=(?P<name>[0-9a-zA-Z_-]*)(\\((?P<args>.*?)\\))?', 5)) { # Just to make life a little easier $full_base = $found[0]; $base_names = $found['name']; $base_args = $found['args']; $base_props = $found['properties']; # Puts the mixin bases into a more suitable array foreach ($base_names as $key => $value) { $bases[$value]['properties'] = $base_props[$key]; # If there are mixin arguments, add them $bases[$value]['params'] = $base_args[$key] != "" ? explode(',', $base_args[$key]) : array(); } # Store this away for debugging self::$mixins = $bases; # Remove all of the mixin bases Scaffold::$css->string = str_replace($full_base, '', Scaffold::$css); } }
/** * Parse the CSS * * @return string - The processes css file as a string * @author Anthony Short **/ public static function parse_css() { # If the cache is stale or doesn't exist if (self::config('core.cache.mod_time') <= self::config('core.request.mod_time')) { # Start the timer Benchmark::start("parse_css"); # Compress it before parsing CSS::compress(CSS::$css); # Import CSS files Import::parse(); if (self::config('core.auto_include_mixins') === true) { # Import the mixins in the plugin/module folders Mixins::import_mixins('framework/mixins'); } # Parse our css through the plugins foreach (self::$plugins as $plugin) { call_user_func(array($plugin, 'import_process')); } # Compress it before parsing CSS::compress(CSS::$css); # Parse the constants Constants::parse(); foreach (self::$plugins as $plugin) { call_user_func(array($plugin, 'pre_process')); } # Parse the @grid Layout::parse_grid(); # Replace the constants Constants::replace(); # Parse @for loops Iteration::parse(); foreach (self::$plugins as $plugin) { call_user_func(array($plugin, 'process')); } # Compress it before parsing CSS::compress(CSS::$css); # Parse the mixins Mixins::parse(); # Find missing constants Constants::replace(); # Compress it before parsing CSS::compress(CSS::$css); foreach (self::$plugins as $plugin) { call_user_func(array($plugin, 'post_process')); } # Parse the expressions Expression::parse(); # Parse the nested selectors NestedSelectors::parse(); # Convert all url()'s to absolute paths if required if (self::config('core.absolute_urls') === true) { CSS::convert_to_absolute_urls(); } # Replaces url()'s that start with ~ to lead to the CSS directory CSS::replace_css_urls(); # Add the extra string we've been storing CSS::$css .= CSS::$append; # If they want to minify it if (self::config('core.minify_css') === true) { Minify::compress(); } else { CSS::pretty(); } # Formatting hook foreach (self::$plugins as $plugin) { call_user_func(array($plugin, 'formatting_process')); } # Validate the CSS if (self::config('core.validate') === true) { Validate::check(); } # Stop the timer... Benchmark::stop("parse_css"); if (self::config('core.show_header') === TRUE) { CSS::$css = "/* Processed by CSScaffold on " . gmdate('r') . " in " . Benchmark::get("parse_css", "time") . " seconds */\n\n" . CSS::$css; } # Write the css file to the cache self::cache_write(CSS::$css); # Output process hook for plugins to display views. # Doesn't run in production mode. if (!IN_PRODUCTION) { foreach (array_merge(self::$plugins, self::$modules) as $plugin) { call_user_func(array($plugin, 'output')); } } } }