• Change the page's HTML to have nice typography #

  • achekalin Reply #1, 2 years, 7 months ago

    Reply
    I spend some time trying to understand if I can do some nice typography characters replacement (by creating some plugin or something) but have no luck yet.

    What I need is to (say) replace dashes, surrounded by spaces (" - ") to em-dashes (" — " - not sure the browser will post that right way). This can be done ina couple of ways: 1) once after page content change, or 2) by change the full page result HTML (right before it outputs to browser).

    First way it the best as it save us CPU cycles on every page generation, but what we should do is to let user to edit the page's content, then to process it with our replacement(s), and to store result in some extra field (or to extra table). Then change code that create pages (by putting content into template) so the code will take our new cache field (or do extra request to our new cache table). This require me to modify core code, something that's not that good idea, I'd prefer to do such a change in a external piece of code (snippet or whatever).

    Second way, to my great sorrow, can be done the same way, by modifying core output code.

    So the question: may there be any way I can intercept site page output (right before page will be send to the user) to have it changed in the way I want and do such intercept in a way (plugin?) that won't be destroyed after next minor modx update (say from 1.0.0 to 1.0.1 or so)? Or it will be wiser to modify modx core code and never mind on updates?


  • bwente Reply #2, 2 years, 7 months ago

    Reply
    That's what plugins are for.

    Description: Filter words from a document before it's displayed on the web
    System Events: OnWebPagePrerender

       $words = array("snippet", "template"); // words to filter  
       $output = &$modx->resource->_output; // get a reference to the output  
       $output = str_replace($words,"<b>[filtered]</b>",$output);
    


    http://svn.modxcms.com/docs/display/revolution/Plugins


  • BobRay Reply #3, 2 years, 7 months ago

    Reply
    I think you might actually want your plugin to listen for onBeforeDocFormSave. That will make the replacements as the doc is saved.

    I've tested this in Revolution. I think it should work in earlier versions.
    Make sure the two arrays match up, member for member.

    $pattern = array(' -- ', '<', '>', etc.);
    $replacement = array('—', '<', '>', etc.);
    $_POST['content'] = preg_replace($pattern, $replacement, $_POST['content']);


  • achekalin Reply #4, 2 years, 7 months ago

    Reply
    Quote from: bwente at Oct 10, 2009, 06:13 PM
    That's what plugins are for.
    ...
    http://svn.modxcms.com/docs/display/revolution/Plugins

    Thank you! I'll try to!

    In fact I messed up with Evolution and Revolution, and yet not sure which Revolution code and ideas can be used for Evolution.


  • BobRay Reply #5, 2 years, 7 months ago

    Reply
    BTW, my code above was taken from a more complicated filter using regular expressions, if you don't need complex pattern matching, you should be able to use str_replace() rather than preg_replace().


  • achekalin Reply #6, 2 years, 7 months ago

    Reply
    BobRay, thank you for the idea, actually the typography plugin is pretty bug piece of code but as far I applied it right to modx_content table content, which is against the whold CMS approach.

    What I really interested is if I put that code in some OnWebPagePrerender-hooked plugin how often will it be executed: 1) on every page view or 2) only once the page content changed and then it output will be cached?

    I suspect it will be executed on every page view, which will be waste of CPU for my site where pages are rarely to change, but I see no better place to have whole page typographed (that is template + all the contents, menu texts etc), not just main content field.



  • achekalin Reply #7, 2 years, 7 months ago

    Reply
    And here is another way I can do nice replacements on page (sorry this is Russian service, but the idea clear in any language):

    http://www.artlebedev.ru/tools/typograf/webservice/TypografWebServiceClient10_php.zip

    this is SOAP-based web-service, and if I use it on every page view then on sites with even descent load it will be slooow, noone will be happy with that. I'd prefer to cache its output...


  • BobRay Reply #8, 2 years, 7 months ago

    Reply
    Quote from: achekalin at Oct 11, 2009, 10:58 AM
    BobRay, thank you for the idea, actually the typography plugin is pretty bug piece of code but as far I applied it right to modx_content table content, which is against the whold CMS approach.

    What I really interested is if I put that code in some OnWebPagePrerender-hooked plugin how often will it be executed: 1) on every page view or 2) only once the page content changed and then it output will be cached?

    I suspect it will be executed on every page view, which will be waste of CPU for my site where pages are rarely to change, but I see no better place to have whole page typographed (that is template + all the contents, menu texts etc), not just main content field.

    OnWebPagePrerender will execute every time the page is viewed. That's why I suggested OnBoforeDocFormSave, which only executes once when the form is saved in the Manager.

    If you want to handle Templates and Chunks too, you can have the plugin listen for OnBeforeDocFormSave, OnBeforeChunkFormSave and OnBeforeTempFormSave.

    You'll need a switch statement in the plugin for each event (note the change in the last line):

    $e = & $modx->Event;
    switch ($e->name) {
       case 'OnBeforeDocFormSave':
       case 'OnBeforeTempFormSave':
               $field = 'content';
               break;
       case 'OnBeforeChunkFormSave':
               $field = 'snippet'; // looks wrong, but it's not
               break;
       
       }
    
    
    $pattern = array(' -- ', '<', '>', etc.);
    $replacement = array('—', '<', '>', etc.);
    $_POST[$field] = preg_replace($pattern, $replacement, $_POST[$field]);



    That way you'll handle documents, chunks and templates as they are saved in the Manager without touching the core code. If you modify the core code, your changes will be overwritten when you update MODx to a new version.


  • achekalin Reply #9, 2 years, 7 months ago

    Reply
    Hmmm, I see your point.

    Frankly, what I tried to accomplish is to keep original (entered by admin) content unmodified while keep cached the result of substitution (and use exactly this result when page to be rendered). The idea is to have whole page looking good in any case. Smart replacements (like doing nice quotes (“” instead of "") or right sized dashes) should be done on the whole page after all snippets etc. is there and processed.

    What I can invent is to have extra field added to modx_content table (let's name it like 'content_cache'), and on OnBoforeDocFormSave I will simple repopulate it with result of substitution. This way the overhead will be there (I will store twice as much content), but the bad news I need to reinject my "cached content" into page rendering later. Really no idea how to do that .

    Another way I see (dumb one but surely to work) is to create some new ("cache") table, where keys will be md5's of page sources and values will be the same sources after replacements. On OnWebPagePrerender we hook simple function that will query DB withd5 of page source to be sent out, and if there is no such a key, we'll simple do our replacement and add the result to out cache table. It it's there we don't need further replacement and simple output the query result. Sound messy, sorry for that, hope you see the idea.

    That you for spending time for my question!


  • BobRay Reply #10, 2 years, 7 months ago

    Reply
    I you're going to use OnWebPagePrerender, I don't see the need for anything beyond a simple plugin. I doubt if the plugin will take more than a few milliseconds to execute. Trying to create your own cache that works in tandem with the MODx cache will give you headaches, IMO, as will modifying the core code or the DB directly.