Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CssOptimizer for ezjscPacker #15

Open
johanberonius opened this issue Sep 21, 2012 · 6 comments
Open

CssOptimizer for ezjscPacker #15

johanberonius opened this issue Sep 21, 2012 · 6 comments

Comments

@johanberonius
Copy link

Nice with an extension that brings less to eZ Publish. But I think maybe it should be implemented as a plugin CssOptimizer for ezjscPacker in ezjscore. Then you could use .less files with ezcss_require/ezcss_load and don't have to reimplement a lot of methods and duplicate code.
Have you given that thought? Any problems with that approach?
See:
https://github.com/ezsystems/ezjscore/blob/master/settings/ezjscore.ini#L14
https://github.com/ezsystems/ezjscore/blob/master/classes/ezjscpacker.php#L470
https://github.com/ezsystems/ezjscore/blob/master/classes/ezjsccssoptimizer.php

@juanolon
Copy link
Collaborator

didn't know ezjscore have plugins... anyway, i will take a look. thanks for the hints.

@johanberonius
Copy link
Author

It does since ezjscore 1.4 I think.
I see that ezless calls all configured optimizers here:
https://github.com/stdclass/ezless/blob/master/autoloads/ezless.php#L324
My idea was that the less compiler could itself be an CssOptimizer and thus use all other functionality for loading, packing etc. from ezjscPacker.
See my css optimizer extension for comparison:
https://github.com/johanberonius/CssInlineImageOptimizer

Another question, is it really safe to store all files that are added in a static class variable?
ezjscore stores these lists in the template variable "persistent_variable" that gets stored in the view cache along with the generated template content. That way css files required by the node tempates are available to the pagelayout even if the node template was never executed and the content taken from view cache.

@johanberonius
Copy link
Author

Of course, if DevelopmentMode is disabled or pack level is 0 ezjscPacker will not even run the CssOptimizers.
And it makes some assumptions on the file extensions being ".css". That might be a limitation for this approach.

@johanberonius
Copy link
Author

I've come up with a much simpler way to use LESS stylesheets together with existing functionality in ezjscore, one Server Function is all it takes.
The less compiler https://github.com/leafo/lessphp/blob/master/lessc.inc.php has to be included in a path scanned by autoload.
Then the class has to be configured as a Server Function in ezjscore.ini

[ezjscServer_myprefix]
Class=myprefixServerFunctions
File=path/myprefixserverfunctions.php
<?php

class myprefixServerFunctions extends ezjscServerFunctions
{    
    /**
     * Compiles the given less-file and appends the generated css-file to the list.
     * Usage in templates: {ezcss_require('myprefix::lessc::file.less')}
     *
     * @param array $args
     * @param array $packerFiles ByRef list of files to pack (by ezjscPacker)
     */
    public static function lessc( $args, &$packerFiles )
    {
        $lessFile = is_array($args) ? $args[0] : $args;
        $cssFile = str_replace('.less', '.css', $lessFile);

        // Only compile less-stylesheets in development mode, in production just return the css-version.
        if ( eZINI::instance()->variable( 'TemplateSettings', 'DevelopmentMode' ) === 'enabled' ) {
            // Find first matching file in design resources
            $bases = eZTemplateDesignResource::allDesignBases();
            $triedFiles = array();
            $match = eZTemplateDesignResource::fileMatch( $bases, 'stylesheets', $lessFile, $triedFiles );
            if ( $match === false ) {
                eZDebug::writeError( "Could not find: $lessFile", __METHOD__ );
            } else {
                $lessPath = $match['path'];
                $cssPath = $match['resource'] . '/' . $cssFile;

                // Compile the less-file
                $less = new lessc;
                try {
                    $less->checkedCompile($lessPath, $cssPath);
                } catch (exception $e) {
                    eZDebug::writeError($e->getMessage(), __METHOD__ );
                }
            }
        }

        array_unshift($packerFiles, $cssFile);
        return '';
    }

    public static function getCacheTime( $functionName )
    {
        // Functions that always needs to be executed, since they append other files dynamically
        if ( $functionName === 'lessc' )
            return -1;

        static $mtime = null;
        if ( $mtime === null )
        {
            $mtime = filemtime( __FILE__ );
        }
        return $mtime;
    }
}

?>

@lendormi
Copy link

lendormi commented Nov 6, 2013

Hi guys,

I have just seen this issue. and i modified ezless.php to implement method like ezscript_require and ezscript load.
code

<?php

    function modify( $tpl, $operatorName, $operatorParameters, $rootNamespace,
                                    $currentNamespace, &$operatorValue, $namedParameters ){
        $ret = '';
        switch ( $operatorName ){
            case 'ezless_imports':
                $operatorValue = $this->registerImports( $operatorValue );
                break;
            case 'ezless_load':
            {
                if ( !isset( self::$loaded['less_files'] ) )
                {
                    $depend = ezjscPackerTemplateFunctions::setPersistentArray( 'less_files', ezjscPackerTemplateFunctions::flattenArray( $namedParameters['script_array'] ), $tpl, false, true );
                    $ret = $this->generateTag( $depend );
                    self::$loaded['less_files'] = true;
                    break;
                }// let 'ezscript' handle loaded calls
                elseif ( $operatorName === 'ezless_load' )
                {
                    $namedParameters['script_array'] = ezjscPackerTemplateFunctions::setPersistentArray( 'less_files', ezjscPackerTemplateFunctions::flattenArray( $namedParameters['script_array'] ), $tpl, true, true, true );
                }
            }
            case 'ezless_add':
            {
                if ( !isset( self::$loaded['less_files'] ) )
                {
                    ezjscPackerTemplateFunctions::setPersistentArray( 'less_files', ezjscPackerTemplateFunctions::flattenArray( $operatorValue ), $tpl, true );
                    break;
                }// let 'ezscript' handle loaded calls
                elseif ( $operatorName === 'ezless_add' )
                {
                    $namedParameters['script_array'] = ezjscPackerTemplateFunctions::setPersistentArray( 'less_files', ezjscPackerTemplateFunctions::flattenArray( $operatorValue ), $tpl, true, true, true );
                }
            }
            case 'ezless':
            {
                $ret = $this->generateTag( $namedParameters['script_array'] );
            } break;
        }
        $operatorValue = $ret;

    }
?>

I hope i help you.

@johanberonius
Copy link
Author

I have since written a "CSS Server Function" that allows for any preprocessors to handle the complete list of files required using standard ezjscore.

In addition to using it with lessphp it can also run external commands. I use it with standard Node.js less-compiler and the brilliant Autoprefixer, https://github.com/ai/autoprefixer

Let me know if there is any interest and I will package it as an extension and share.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants