Tweaking WordPress’s Expound theme’s menu

I’m helping on a site for a not-for-profit for which we selected “Expound” as the base theme. I like Expound; it looks great, there’s no jQuery- or webfont-cruft to worry about and although the CSS comes with a seperate reset.css-file, it does (Auto-)optimize perfectly.
But I wasn’t happy with the menu color-scheme and with the fact that the menu lacked an indication that a child page of a main entry was being shown instead of the page of that main entry itself (confused much?).
Anyway, this is what I ended up with;
wordpress expound theme menu tweaked
For those wanting to do something similar, this is the relevant CSS in my child theme;

/* don't want no blue */
.navigation-main .current-menu-item > a {
        background: #557B47 !important;
}
/* triangle should not be blue either, need it to be a bit bigger */
.navigation-main ul > .current_page_item a:after, .navigation-main ul > .current-menu-item a:after, .navigation-main ul > .current-post-ancestor a:after, .navigation-main ul > .current-menu-parent a:after, .navigation-main ul > .current-post-parent a:after {
        border-top: 10px solid #557B47 !important;
        bottom: -14px;
        z-index: 1000;
}
@media screen and (min-width: 600px) {
  /* if page from submenu, add line under parent item to show your in that submenu */
  .navigation-main ul > .menu-item {
        border-bottom: 6px solid #3A3A3A !important;
  }
  .navigation-main ul > .current_page_item, .navigation-main ul > .current-menu-item, .navigation-main ul > .current-post-ancestor, .navigation-main ul > .current-menu-parent, .navigation-main ul > .current-post-parent {
        border-bottom: 6px solid #557B47 !important;
  }
  /* but not in submenu */
  .navigation-main .sub-menu > .menu-item {
        border-bottom: 0px !important;
  }
  /* less padding at the bottom to compensate for that extra line */
  .navigation-main a {
        padding: 10px 10px 4px !important;
  }
  /* except when in submenu */
  .navigation-main .sub-menu a {
        padding: 10px !important;;
  }
}
/* change color to default brown if child-item is active */
.navigation-main ul > .current_page_item, .navigation-main ul > .current-menu-item, .navigation-main ul > .current-post-ancestor, .navigation-main ul > .current-menu-ancestor, .navigation-main ul > .current-menu-parent, .navigation-main ul > .current-post-parent {
        background: #3A3A3A !important;
}

Have fun!

Mijn alternatief voor m.deredactie.be

Dat ik niet content was met de vernieuwde mobiele redactie.be schreef ik hier al. Maar commentaar spuien kan iedere blogger, afbreken is makkelijker dan opbouwen en het beste argument is een uitgewerkt alternatief. Vandaar; ik werkte de afgelopen maanden tussen de soep en de patatten aan een eigen “progressive enhanced” Proof of Concept van een mobiele deredactie.be (in PHP) die op alle browsers werkt, minder mobiele data verbruikt en sneller rendert (hier moet ge zijn, ongeduldigaard).
Waarom ik denk dat deze aanzet beter is dan de officiële versie van de VRT? Wel, de POC

  • futttas-redactie-pagespeed-insightsis op elke browser te bekijken, ook als er geen (of slechte) JavaScript-ondersteuning is. Opera Mini? Lynx? De Netfront op uw grootvader’s Nokia? Geen probleem!
  • kan makkelijk uitgebreid worden om afhankelijk van context de presentatie anders toe doen, bv. op tablet de nieuwscategorieën permanent aan de linkerkant
  • de download-size is véél kleiner (en vreet dus minder van uw mobile data-abonnement); 472KB (document complete) en 979KB (fully downloaded) vs 126 en 127KB
  • de site rendert véél sneller (en spaart uw batterij dan ook meer); 7.419s vs 1.557s
  • Google PageSpeed Insight geeft m.deredactie.be een mobile score van 61/100 tegenover 97/100 voor deze POC (91/100 indien de data niet uit de cache, maar van VRT komt)

Je kunt:

Een paar technische feitjes;

  • De basis-versie werkt volledig zonder JavaScript. Als JS aanwezig is en “up to snuff” (cfr. cut the mustard), wordt de ervaring “verrijkt” (fixed header, uitklapbare navigatie, lazy-loading van images …).
  • Alle CSS en JS staat -weliswaar slordig maar oh zo performant- inline (behalve aniHead.js, een onafgewerkte en dus inactieve “verrijkings”-PoC in de PoC, type aniHead(); in de console om te activeren).
  • De POC gebruikt dezelfde data-feeds als m.deredactie.be, maar haalt die server-side binnen (dependancy; Curl)
  • Data wordt -gecomprimeerd- gecachet in APC cache (dependancy; APC)
  • Externe HTML in de data-feeds (iframe, script of object van bv. Twitter & Facebook) wordt rudimentair weggefilterd, maar dat is een optie in de code ($trustHTML=false;)
  • De code-kwaliteit is ongetwijfeld beneden alle peil (geen OO, geen MVC, veel spaghetti), maar ik ben dan ook geen èchte developer.
  • Grootste missing feature is video (er zijn er nog, zie Trello-board)

Zo, dat is het zo wat. Bekijk het eens, geef commentaar, fork op GitHub, fix bugs, voeg features toe. Maar wat je ook doet, vergeet niet dat de content van VRT is en blijft en dat je daar dus niet zomaar wat mee kunt doen.

(When) should you Try/Catch Javascript?

Autoptimize comes with a “Add try-catch wrapping?”-option, which wraps every aggregated script in a try-catch-block, to avoid an error in one script to block the others.
I considered enabling this option by default, as it would prevent JS optimization occasionally breaking sites badly. I discussed this with a number of smart people and searched the web, eventually stumbling on this blogpost which offers an alternative for try-catch because;

Some JavaScript engines, such as V8 (Chrome) do not optimize functions that make use of a try/catch block as the optimizing compiler will skip it when encountered. No matter what context you use a try/catch block in, there will always be an inherent performance hit, quite possibly a substantial one. [Testcases] confirm [that] not only is there up to a 90% loss in performance when no error even occurs, but the declination is significantly greater when an error is raised and control enters the catch block.

So given this damning evidence of severe performance degradation, “try/catch wrapping” will not be enabled by default and although Ryan’s alternative approach has its merits, I’m weary of the caveats so I won’t include that (for now anyway). If your site breaks when enabling JS optimization in Autoptimize, you can enable try/catch wrapping as a quick workaround, but finding the offending script and excluding it from being optimized is clearly the better solution.

My Adventures on OpenShift

openshiftI have always been a fan of Red Hat, even if have never used their products extensively. They were one of the original movers in Linux-market back when Slackware was big and when InfoMagic CD-rom boxes with multiple distro’s were popular. And I have remained a fan because they succeeded in building a solid company built on and around open source & services.
So I was very happy to read that Red Hat had entered the PAAS-market with OpenShift, that that platform was built on open source(d) solutions and that a small-timer like me could deploy apps for free on their application cloud. I signed up, installed the WordPress instant application, added some tried & tested plugins and imported my content. Half an hour works, tops and performance proved to be great. Everything was just peachy, until I received this message in my mailbox;

We believe your use of OpenShift violates the Services Agreement and Acceptable Use Policy both of which can be found here: https://openshift.redhat.com/app/legal/
Infected file(s):
/var/lib/openshift53bcc3fd5973cabac00000d1/.tmp/53bcc3fd5973cabac00000d1/just_test_bc: Perl.Shellbot-8

And ZAP, my application was removed. As I had no idea how “just_test_bc” ended up in a temp-folder, the only possibility was a successful hack-attempt, so I contacted the security team to get more information. It took some time (and an escalation via the Customer Enablement Team), but I eventually got in touch with Stefanie at Red Hat, who was able to provide me with more information:

It looks like we had a one-off error in the script that emailed you. Your application was still flagged, but on a different file than we emailed about. This is the actual file:
/var/lib/openshift/53bd21435973cad637000080/mysql/data/ib_logfile0: PHP.ShellExec
So there was something in the mysql database log that set off the scan. […] It looks like mysql may have logged someone’s attempt to inject some bad PHP code into your app.

ib_logfiles are MySQL’s innodb replay log files and as Stefanie provided me with a tarball with my entire application, I extracted ib_logfile0 and used “strings” to extract readable information from the binary file. The result (from my mail to Stefanie);

Although php’s exec (and similar functions) can be found [in the logfile], this is always due to … blogposts about web security and specifically this one; http://blog.futtta.be/2007/12/02/php-security-eval-is-evil/. The content of that article was inserted in the DB and [thus] added to ib_logfile. Your scanner finds the content [in that innodb replay logfile] and flags this as a problem. I would think the OpenShift scanner needs some finetuning, [as now] anyone is at risk of having their app auto-removed if the mysql-redo-logfile happens to contain vaguely “offending” strings such as shell_exec?

OpenShift confirmed this analysis;

You’re absolutely right that our scanner needs work. So what I’m going to do is get you onto a whitelist so this thing doesn’t flag you again. […] All takedowns are currently on hold until I can implement pre-removal notifications [and] improve our standard operating procedure for this kind of thing. That should give people a chance to tell us that their apps are not malicious, so that we can whitelist others too, if needed. As long as they notice an email saying “OpenShift Terms Of Service Violation” within a few days, I think they should be safe. If they do get flagged as a false positive like your app did, they’ll email us back and let us know it’s a mistake, and then they’ll be added to the whitelist too.

Now wasn’t that an interesting adventure? If ever you get a notification-mail from OpenShift related to security issues, check if the problem isn’t with benign content being inserted in the database and if so be sure to contact OpenShift so they can add you to their whitelist.

PHP HTML parsing performance shootout; regex vs DOM

As I wrote earlier an Autoptimize user proposed to switch from regular expression based script & style extraction to using native PHP DOM functions (optionally with xpath). I created a small test-script to compare performance and the DOM methods are on average 500% slower than the preg_match based solution. Here are some details;

  • There are 3 tests; regular expression-based (preg_match), DOM + getElementsByTagName and DOM + XPath. You can see the source here and see it in action here.
  • The code in all 3 testcases does what Autoptimize does to start with when optimizing JavaScript:
    1. extract all javascript (code if inline, url if external) and add it to an array
    2. remove the javascript from the HTML
  • With each load of the test-script, the 3 tests get executed 100 times and total time per method is displayed.
  • That test-script was run 5 times on 3 different HTML-files; one small mobile page with some JavaScript and two bigger desktop ones with lots of JS.

The detailed results;

total time regextotal time domtotal time dom+xpath
arturo’s HP0.6114.83664.977
deredactie HP2.33225.6155.879
m deredactie HP0.06960.46040.4558

So while parsing HTML with regular expressions might be frowned upon in developer communities (and rightly so, as a lot can go wrong with PCRE in PHP) it is vastly superior with regards to performance. In the very limited scope of Autoptimize, where the regex-based approach is tried & tested on thousands of blogs, using DOM would simply create too much overhead.

Some HTML DOM parsing gotchas in PHP’s DOMDocument

Although I had used Simple HTML DOM parser for WP DoNotTrack, I’ve been looking into native PHP HTML DOM parsing as a possible replacement for regular expressions for Autoptimize as proposed by Arturo. I won’t go into the performance comparison results just yet, but here’s some of the things I learned while experimenting with DOMDocument which in turn might help innocent passers-by of this blogpost.

  • loadHTML doesn’t always play nice with different character encodings, you might need something like mb_convert_encoding to work around that.
  • loadHTML will try to “repair” your HTML to make sure an XML-parser can work with it. So what goes in will not come out the same way.
  • loadHTML will spit out tons of warnings or notices about the HTML not being XML; you might want to suppress error-reporting by prepending the command with an @ (e.g. @$dom->loadHTML($htmlstring);)
  • If you use e.g. getELementsByTagName to extract nodes into a seperate DomNodeList and you want to use that to change the DomDocument can result in … unexpected behavior as the DomNodeList gets updated when changes are made to the DomDocument. Copy the DomNodes from the DomNodeList into a new array (which will not get altered) and iterate over that to update the DomDocument as seen in the example below.
  • removeChild is a method of DomNode, not of DomDocument. This means $dom->removeChild(DomNode) will not work. Instead invoke removeChild on the parent of the node you want to remove as seen in the example below
// loadHTML from string, suppressing errors
$dom = new DOMDocument();
@$dom->loadHTML($html);
// get all script-nodes
$_scripts=$dom->getElementsByTagName("script");
// move the result form a DomNodeList to an array
$scripts = array();
foreach ($_scripts as $script) {
   $scripts[]=$script;
}
// iterate over array and remove script-tags from DOM
foreach ($scripts as $script) {
   $script->parentNode->removeChild($script);
}
// write DOM back to the HTML-string
$html = $dom->saveHTML();

Now chop chop, back to my code to finish that performance comparison. Who know what else we’ll learn 😉

Should you inline or defer blocking CSS?

CSS codeYou care about web performance and so you dutifully aggregate and minify your CSS. But then a couple of months ago Google PageSpeed Insights (for mobile) started identifying CSS as a render blocking resource and so you wonder if you should you inline your CSS, or even defer loading it. Based on tests executed on a multi-site WordPress installation, deferring CSS is not the best idea just yet, but inlining might be worthwhile! Read on for the hard numbers and other details.

The test-setup

  • 4 test-blogs on a multi-site WordPress instance
  • using the Expound theme (which is interesting because its main stylesheet imports 2 other CSS-files)
  • using Lite Cache for page caching (new WordPress page caching plugin by the Hyper Cache author)
  • the same content was imported on all 4 blogs
  • all 4 had Autoptimize HTML & JS optimization active
  • the difference was in the Autoptimize CSS settings, where:
    • blog 1 had no CSS optimization at all (baseline )
    • blog 2 had standard CSS aggregation and minification, linked in head
    • blog 3 inlined the optimized CSS
    • blog 4 deferred the optimized CSS
  • each blog was tested on webpagetest.org‘s Amsterdam node on a DSL-profile using IE9 and doing 9 test-runs on one specific blogpost with contained a 16KBimage (I excluded favicon.ico as it seemed to pollute results)
  • each blog was analyzed by Google PageSpeed Insights for both mobile & desktop

The results

test report urlfirst bytestart renderdoc completefully loadedmobile pagespeeddesktop pagespeed
1. no css optimization140212_Z1_MKN0.299s2.246s2.221s2.221s7992
2. optimized CSS linked140212_H7_MKP0.239s0.608s1.390s1.390s9197
3. optimized CSS inlined140212_A3_NJA0.232s0.348s0.658s0.658s9999
4. optimized CSS deferred 140212_8J_P1G0.248s0.357s1.034s1.034s9995

The conclusions

Based on these tests (your mileage may vary, always test your results):

  • deferring all CSS is useless, performance is worse, desktop PageSpeed score is (slightly) lower and there is a “flash of unstyled content” between the rendering of the page and the application of the CSS.
  • Inlining CSS yields the best results both from a page speed and PageSpeed perspective. Although the base HTML is larger as it has the CSS payload, this has almost no impact in this specific context and rendering is almost instantaneous. Off course in a context where multiple other pages from the same site, with the exact same CSS would be loaded, the impact would be significant. Hence inlining CSS is especially interesting for sites with a low pageviews/ visitor ratio.

The future; inline + defer

Deferring CSS may seem pretty useless, but the sweet spot may just be inlining base CSS (everything needed for initial rendering above the fold) and deferring everything else. This is what CSS optimizing tools should focus on in 2014 and you can certainly expect something along these lines in one of the next major Autoptimize releases (although diehards can already test this approach).

Irregular Expressions have your stack for lunch

I love me some regular expressions (problems), but have you ever seen one crash Apache? Well I have! This regex is part of YUI-CSS-compressor-PHP-port, the external CSS minification component in Autoptimize, my WordPress JS/CSS optimization plugin:
/(?:^|\})(?:(?:[^\{\:])+\:)+(?:[^\{]*\{)/)/
yo regex dawgExecuting that on a large chunk of CSS (lots of selectors for one declaration block, which cannot be ripped apart) triggers a stack overflow in PCRE, which crashes Apache and shows up as a “connection reset”-error in the browser.
Regular expression triggered segfaults are no exception in the PHP bugtracker and each and every of those tickets gets labeled “Not a bug” while pointing the finger at PCRE, which in their man-pages and in their bug tracker indeed confirm that stack overflows can occur. This quote from that PCRE bug report says it all, really;

If you are running into a problem of stack overflow, you have the
following choices:
  (a) Work on your regular expression pattern so that it uses less
      memory. Sometimes using atomic groups can help with this.
  (b) Increase the size of your process stack.
  (c) Compile PCRE to use the heap instead of the stack.
  (d) Set PCRE's recursion limit small enough so that it gives an error
      before the stack overflows.

Are you scared yet? I know I am. But this might be a consolation; if you test your code on xampp (or another Apache on Windows version), you’re bound to detect the problem early on, as the default threadstacksize there is a mere 1MB instead of the whopping 8MB on Linux.
As for the problem in YUI-CSS-compressor-PHP-port; I logged it on their Github issue-list and I think I might just have a working alternative which will be in Autoptimize 1.8.

You gotta love HTML5’s input types and patterns

While working on updates of the admin-screen of Autoptimize, I wanted some checks on the URL a user can enter for a CDN. At first I thought I’d do some jQuery-based validation but then I came accross a page (on StackOverflow I guess) that mentioned the new input types and the use of validation patterns, so now I just have this beauty in place;

<input type="url" pattern="^(https?:)?\/\/([\da-z\.-]+)\.([\da-z\.]{2,6})([\/\w \.-]*)*\/?$" />

And to make sure the user gets a visual indication if the string isn’t a valid URL (according to the regex) there’s this CSS oneliner:

input[type=url]:invalid {color: red; border-color:red;}

The nice thing about this is that it is pretty backwards compatible;

  1. browsers that do not know type=”url” will just consider it type=”text” and can still enforce the pattern (if supported).
  2. browsers who support type=”url” but not the pattern, will do more basic validation.

And for browsers that do not support type=”url” nor patterns, there are multiple polyfills available that force older browsers to comply as well. But who cares about older browsers, right?

Power users rejoice; WP YouTube Lyte has an API

Power users of WP YouTube Lyte might be particularly interested in the version that is being pushed out as we speak. 1.3.0 comes with an API, allowing you to substantially change the way the plugin works.
You have the following filters to play around with;

  • lyte_settings; filter to change values in the settingsArray without changing the actual setting
  • lyte_content_preparse; filter to change the_content before the httpv-links are being parsed
  • lyte_match_preparse_fragment; filter to change an individual httpv-link before it is parsed
  • lyte_match_postparse_template; filter to change the parsed code before it is merged back in the_content
  • lyte_content_postparse; filter to parse the_content before it is being handed over to the next plugin
  • lyte_css; filter to change WP YouTube Lyte’s CSS
  • lyte_actionsfilters; action to add extra actions or filters, e.g. to make sure widget_text is parsed by lyte_parse as well

The plugin now comes with “lyte_helper.php_example” which is an sample plugin file that, when copied to “/wp-content/plugins/lyte_helper.php” can be activated as a separate plugin and which contains examples of how the API can be used.
For the less tech-savvy users, these are some of the other changes in 1.3.0 (from the changelog):

  • Support for higher quality thumbnails by adding #hqThumb=1 to httpv-link
  • You can disable microdata on a per-video level by adding #noMicrodata=1 to the httpv-link when microdata is enabled.
  • Checkbox on admin-page to flush WP YouTube Lyte cache (which holds title, description, … from YouTube)

As always; feedback, bug reports, feature requests, criticism or code suggestions are more then welcome in the comments or via the contact form.
But whatever you do, make sure to have fun while doing it! This embedded YouTube audio track (a 2h BBC essential mix by Flying Lotus from back in 2008) might help, if you’re into that type of music that is;

Flying Lotus Essential Mix - All 2 Hours - 2008-11-29 High Quality