Coded something up in Couch in an interesting way? Have a snippet or shortcode to share? Post it here for the community to benefit.
10 posts Page 1 of 1
Hi, some cool new tag here: <cms:trim />.
EDIT: Also read new posts below for adding new functionality for stripping off HTML comments and PHP-like comments. More details also given below about enabling automatic minify for all code generated by CouchCMS.

New tag <cms:trim /> can normalize white-spaces, removing double spaces and trimming space-like characters (new lines, tabs, etc) from both ends of the string passed to it.

I got inspiration to make up this tag after reading an article here http://pageconfig.com/post/remove-undes ... im_all-php

CouchCMS 2.0+ has some part of this enabled by default with removing only spaces caused by tags (not exactly the same implementation). So <cms:trim /> can extend this to a greater level.

For all Couch versions <cms:trim /> is cool for minifying purposes.

The code below goes to /cms/addons/kfunctions.php (It is fairly working copy-paste).
Code: Select all

$FUNCS->register_tag( 'trim', array('CustomTags', 'trim_all') );
class CustomTags{
   
    function trim_all( $str, $node ){

        $res = $str[0]['rhs'];
        return trim( preg_replace( "/\s+/" , ' ' , $res ) , " \t\n\r\0\x0B" );
    }
   
}


Usage: <cms:trim var />
(<cms:show var /> can be safely changed to <cms:trim var />)
For snippets:
Code: Select all
<cms:trim "<cms:embed 'snippet.html' />" />

Works great and fast.

Hope this helps minify some byte-waste across the planet. :D

Important tip to use with large sparse chunks, like those, generated by html/css layout, cms:pages etc.: cms:trim works like <cms:show />, so it is possible to do this thing:
Code: Select all
<cms:capture into='page_listing' >
          ... whatever ...
</cms:capture>
<cms:trim page_listing />

The code above saves whatever into some new variable named page_listing and outputs it minified.

P.S. Welcome with suggestions and mod requests.
Code: Select all

    function trim_all( $str, $node ){

        $res = $str[0]['rhs'];
        return trim( preg_replace( "/\s+/" , ' ' , $res ) , " \t\n\r\0\x0B" );
    }



Code above is a simplified version of 'trim', which removes multiple spaces and new lines. Previous version was seen to remove double zeros in the end of the string, like '500' becomes '5', if nothing is after it. This posted version will not do it, I gladly report after hitting this wall myself. :)

You can have various tags in kfunctions.php inside one class, like below (with md5 tag).
Code: Select all


$FUNCS->register_tag( 'md5', array('CustomTags', 'md5_hasher') );
$FUNCS->register_tag( 'trim', array('CustomTags', 'trim_all') );

class CustomTags{
   
    function md5_hasher( $params, $node ){
       
        if( count($node->children) ) {die("ERROR: Tag \"".$node->name."\" is a self closing tag");}
      $res = $params[0]['rhs'];
        return md5( $res );
    }

    function trim_all( $str, $node ){

        $res = $str[0]['rhs'];
        return trim( preg_replace( "/\s+/" , ' ' , $res ) , " \t\n\r\0\x0B" );
    }

}

trendoman can you illustrate the effect of this trick - for example picture screen
thanks
@orbital, if you check generated source in browser via source-view or Inspect in chrome, you can see that in couch 1.4.7 generated html-code has many empty lines. Sometimes empty space is a result of embedding snippets with calculations.

cms:trim helps remove those spaces.
Yes - I know that, but I already have version 2 - then this code does it matter?
Hi Mate!

Do you have a live site that i can take a look how the minifying output on the page source?


Thx!
As soon as possible!

Touch me up : abada[dot]zulma[at]gmail[dot]com
Code updated. Now removes extra spaces without errors.
Now sample.
Before:
ScreenCut-12-06---13-41-14-.png
Without <cms:trim />
ScreenCut-12-06---13-41-14-.png (13.35 KiB) Viewed 514 times

After:
ScreenCut-12-06---13-41-35-.png
With <cms:trim />
ScreenCut-12-06---13-41-35-.png (39.33 KiB) Viewed 514 times


Handy for massive number of opt_values in selects/checkboxes/dropdowns, also handy for embedding snippets with sparse code.
Now usage.
Code: Select all
Instead of <cms:show some_variable /> use <cms:trim some_variable /> - it will show trimmed output.

For snippets can be used like this:
Code: Select all
<cms:trim "<cms:embed 'snippet.html' />" />
Code improved and updated.
Sometimes total minification is required :)
To make all webpages, generated by CouchCMS completely minified automatically, add this to kfunctions.php:
Code: Select all
$FUNCS->add_event_listener( 'alter_final_page_output', array('CustomTags', 'total_minification') );

class CustomTags{

    function total_minification (&$html){
        $html = preg_replace('/<!--.+?-->/', '', $html);
        $what = array( '> <',  '" >', '" />' );
        $with = array( '><', '">', '"/>' );
        $html = trim( preg_replace( "/\s+/" , ' ' , $html ) , " \t\n\r\0\x0B" );
        $html = str_replace( $what , $with , $html );
        return 1;
    }

}



This regex pattern matches comments with any content in them.
/<!--.+?-->/

These 3 strings match unnecessary spaces in between HTML tags, also before closing braces.
'> <', '" >', '" />'

These special characters are: an ordinary space, a tab, a new line, a carriage return, the NUL-byte, a vertical tab.
\t\n\r\0\x0B


Then the result would look like this:
ScreenCut-12-26---12-04-43-.png
Minification Sample
ScreenCut-12-26---12-04-43-.png (195.96 KiB) Viewed 455 times


I took some inspiration from this thread and another one viewtopic.php?f=4&t=7223

Edit:

To disable minification, comment out the line in kfunctions.php like this:
// $FUNCS->add_event_listener( 'alter_final_page_output', array('CustomTags', 'total_minification') );


EditEdit:
Adding the following lines helps strip php-like /* comments */ from the code:
Code: Select all
        $what = array( '`\/\*\*.*`', '`(?:\/\*[\s\S]*?\*\/)+?`', '`.*\*\/`' );
        $with = array( '', '', '' );
        $html = preg_replace( $what, $with, $html);

First set of regex (?:\/\*[\s\S]*?\*\/)+? removes comments enclosed with /* */, just like PHP does.

Anything like that will be removed:
Code: Select all
/* this is a comment */ 
/*
   this
   is
   a comment
*/

Second set of regex \/\*\*.* removes only single-line comments, anything that comes after /** , for example:
Code: Select all
/** This comment will be removed
This line is visible

If you initially placed /** with intentions to write 1 line of comment and then decided to expand to multi-line comment with more text, then a third set of regex .*\*\/ will take care of any comment ending with */. So simply add closing brace */ like in following sample:
Code: Select all
/** I wrote this line of comment
    And decided to expand it later */


This essentially helps to replace the required use of <cms:ignore /> tag.
Code: Select all
<cms:ignore >comment</cms:ignore>


Attention: CouchCMS will also execute its code in comments.

For the solution to also easily comment-out CouchCMS tags you'll have to make some changes. First, we can't paste the 2 lines above to the minification function, because this minification runs after the CMS has generated the code.
Instead, we will create a new function, that runs before CouchCMS parser steps in.
In this new function we will place our code that removes comments and any couch tags in them. Couch tags will not be executed in comments.
Code: Select all
$FUNCS->add_event_listener( 'pre_process_page', array('CustomTags', 'remove_comments') );

class CustomTags{

    function remove_comments (&$html){
        $what = array( '`\/\*\*.*`', '`(?:\/\*[\s\S]*?\*\/)+?`', '`.*\*\/`' );
        $with = array( '', '', '' );
        $html = preg_replace( $what, $with, $html);
    }
}


Currently, CouchCMS fires "pre_process_page" event only for the complete code, after all snippets have been embedded successfully, so if we would like to remove comments from the snippets, there are 2 ways - first, normal way, let Couch execute the couch tags in comments during the "generation" stage and when the final HTML output is successfully generated by the CMS - we hook into the "alter_final_page_output" and remove the comments. This should suffice for normal use-cases.

On the other hand, very often commenting helps to disable some problematic code that generates errors. In this case we should strip out comments with problematic code before couchcms senses those unclosed tags, missing parameters and other trouble-makers. I guess, only very simple code can be written without errors even for experienced coders. And debugging is sometimes not an easy task, but a time-consuming one. Let's keep the problematic code in the file itself, but comment it out - very similar to PHP, which doesn't execute code in comments.

This task respects the existing Couch way so we just remove those comments off the HTML after it has been read from the snippet file. To do this, let's add a new event to function embed in couch/tags.php so it fires right before the content of the snippet is ready to be sent to CouchCMS.

In couch/tags.php find a function embed and find this piece:
Code: Select all
if( $html ){

    $parser = new KParser( $html, $node->line_num, 0, '', $node->ID );
    return $parser->get_HTML();
}

Make it look like this instead:
Code: Select all
if( $html ){

    // HOOK: alter_file_contents
    $FUNCS->dispatch_event( 'alter_file_contents', array(&$html) );

    $parser = new KParser( $html, $node->line_num, 0, '', $node->ID );
    return $parser->get_HTML();
}


Now we are ready to wait for this event and strip comments.
Add an even listening function to couch/addons/kfunctions.php, which will make use of our previous function remove_comments:
Code: Select all
$FUNCS->add_event_listener( 'alter_file_contents', array('CustomTags', 'alter_embed') );

class CustomTags{

    function alter_embed (&$html){
        CustomTags::remove_comments( $html );
        return 1;
    }
}


If you choose to have both functions - to remove comments before couch steps in & to minify the source after couch generated it, then paste this combined code into couch/addons/kfunctions.php
Code: Select all
$FUNCS->add_event_listener( 'alter_file_contents', array('CustomTags', 'alter_embed') );
$FUNCS->add_event_listener( 'pre_process_page', array('CustomTags', 'remove_comments') );
$FUNCS->add_event_listener( 'alter_final_page_output', array('CustomTags', 'total_minification') );
class CustomTags{

    function alter_embed (&$html){
        CustomTags::remove_comments( $html );
        return 1;
    }

    function total_minification (&$html){
        $what = array( '> <',  '" >', '" />' );
        $with = array( '><', '">', '"/>' );
        $html = preg_replace('/<!--.+?-->/', '', $html);
        $html = trim( preg_replace( "/\s+/" , ' ' , $html ) , " \t\n\r\0\x0B" );
        $html = str_replace( $what , $with , $html );
        return 1;
    }

    function remove_comments (&$html){
        $what = array( '`\/\*\*.*`', '`(?:\/\*[\s\S]*?\*\/)+?`', '`.*\*\/`' );
        $with = array( '', '', '' );
        $html = preg_replace( $what, $with, $html);
        return 1;
    }

}


Code: Select all
/** A single line comment
/* this is also a comment */
/*
   this
   is a broken and unfinished code with a CouchCMS tag: <cms:input type="text...
   which also gets removed
*/   
This will be also removed correctly */


EditEditEdit:
CouchCMS 2.0 once released will have a new HOOK (kudos @KK) alter_str_to_parse, that comes handy for altering strings that come to parser.
Then it can work like this:
Code: Select all
$FUNCS->add_event_listener( 'alter_str_to_parse', array('CustomTags', 'remove_comments') );
Update. Now leaving alone "<![CDATA[ " (essential for CKEditor to work) and other improvements.

Code: Select all

$FUNCS->add_event_listener( 'alter_final_page_output', array('CustomTags', 'total_minification') );


class CustomTags{

    function total_minification (&$html){

        $what = array( /*'%\s+%',*/ '%<!--(.|\s)*?-->%', '%(?://)?<!\[CDATA\[(.*?)(?://)?\]\]>%' );
        $with = array( /*' ',  */   '',                  "//<![CDATA[\n".'\1'."\n//]]>"          );
        $html = preg_replace( $what , $with , $html );

        $what = array( '%>\s+<%', '%"\s+>%', '%"\s+/>%', "%'\s+>%", "%'\s+/>%" );
        $with = array( '><'     ,  '">'    , '"/>'     , "'>"     , "'/>"      );
        $html = preg_replace( $what , $with , $html );

        $html = trim( $html, " \t\n\r\0\x0B" );

        return 1;
    }
}



+ parser.php with the new HOOK alter_final_page_output, for 1.4.7.

V.IMP:
After more thorough study I realized that writing a good minify plugin from scratch would be a mistake.
Currently in the code above I disabled removing new-lines, because newlines are also removed from inline JS. Removing newlines kills scripts, obviously, because of inline comments. Also newlines must be preserved in <pre, textarea, code, etc>. So a simple solution that I initially presented just doesn't work :) Then I studied some code samples from internet and there are so many rules to make this addon work properly. The biggest one I saw was here https://github.com/mecha-cms/extend.minify So maybe some day I'll take on the exercise to adapt good 3rd party function. So far, I think minification should be disabled if you have embedded JS in code, CDATA], CSS etc. :roll: :)

Attachments

10 posts Page 1 of 1

Who is online

In total there are 2 users online :: 0 registered, 0 hidden and 2 guests
(based on users active over the past 5 minutes)

Users browsing this forum: No registered users and 2 guests