Nov 10 2007

Enzymes 2.0 Released Today

Tag: EnzymesAndrea Ercolino @ 23:55:43

Enzymes is a Wordpress Plugin for retrieving properties and custom fields of posts, pages, and authors, right into the visual editor of posts and pages, and everywhere else.

I’m releasing now Enzymes 2.0 which is quite a step forward. The features are

  • a new syntax for retrieving properties of posts, pages, and authors; as well as the old syntax for custom fields
  • a new syntax for identifying posts and pages by means of their slugs; as well as the old syntax with their numbers
  • a new elaborate method allowing for an easier processing of indirect arguments
  • a new merging method helping at crafting how the pathway is built by evaluation enzymes
  • slash and backslash templating uniformly supported by transclusion and evaluation enzymes
  • a cleaner code
  • a new manual
  • new examples
A WordPress Plugin

This version is available for download from wordpress.org

The previous version

I released Enzymes 1.2 one year ago from mondotondo.com, and re-released it as version 1.3 one month ago from wordpress.org. Both were almost the same thing. Here are the only differences:

  • updated the description header, accounting for the new address (notelog.com)
  • removed the signals to my server for activation / deactivation of the plugin
  • packaged as a wordpress plugin, available for download from wordpress.org

Mar 02 2007

How to add semantics to WordPress posts

Tag: EnzymesAndrea Ercolino @ 10:49:35

Browsing the WordPress’ ideas repository I’ve found one that could make WordPress fill the gap between a blog tool and a knowledge base: Structured Blogging.

The fact that it got 60 votes but only 50% stars means two things:

  1. voting people are lazy thinkers
  2. it’s a difficult task at many levels

Nonetheless it’s a good idea because this is and will be for many years to come the blogging era, where millions of authors post content to the Internet. There is no good reason for that content to be unstructured except lazyness and complexity.

Nothing can be done about lazyness but complexity can be substantially reduced. The solution needs:

  • a mechanism for adding XML tags from some dictionary
  • a template system for showing XML content appropiately

On the path to something readily usable (I hope Matt will provide it in WordPress 3.0), a mechanism could be a jQuery plugin for the visual editor, and a template system could be based on Enzymes.

Autocompletion

I think that tinyMCE can be extended by plugins, but I don’t know how to. jQuery itself has an autocompletion plugin that could be used this way. When an author presses a < key, the autocompletion gets triggered and the popup … pops up :-)

If you have ever used IME (for Japanese for example), you should know what I mean. Options are organized in a hierarchy and you get the most relevant at the top, depending on the few characters already typed. XML dictionaries could be ajaxed and locally cached; they could be plugins that you install into your blog, or be web services too; they could be international standards compliant or be completely custom.

The most-relevant-first feature of the autocompletion popup would be a big help for authors. If I already opened a Tag, then the most relevant options after pressing < could be:

  1. the closing tag for that Tag
  2. any tag that could be inside that Tag (properly sorted if needed)
  3. any root of the cached dictionaries (if possible in Tag)
  4. an option for accessing additional dictionaries (if possible in Tag)

Templates

A PHP template for properly rendering XML content is very easy to write, and Enzymes could be used in the clockwork. In fact an Enzymes feature is the possibility of easily transcluding all the content of a post or a page by means of the special char *

The XML to HTML template can be transformed in an Enzymes template with a couple of PHP instructions, thus allowing you to almost copy and paste already available templates. Then you could apply a solution like this:

  1. write a private post or page with the XML content, using the autocompletion feature described above (say this post is #123)
  2. write a public post or page with the Enzymes statement {[123.* /template.php]} in its content

The post in 1. needs to be private because you don’t want it to appear on the blog as is, and 2. makes the transformation happen. As an added benefit, you can display that semantic content inside of a greater context, and you can transclude it wherever you want in your WordPress blog (as many times as you like).


Feb 16 2007

How to Highlight Mixed Language Source Code

Tag: Chili, EnzymesAndrea Ercolino @ 16:35:29

Web pages contain many snippets from different languages, like HTML, PHP, CSS, and JavaScript. Chili 1.x cannot highlight mixed language source code automatically, but the forthcoming released Chili 2.0 will be is able to do that.

Meanwhile, if you are using a Chili + Enzymes setup, then it’s possible to write an Enzymes template capable of making Chili 1.x highlight a web page perfectly (expanding on my previous php template).

Here is the new updated (2007/02/19) chili-web.php Enzymes template. At the moment it supports XHTML, and embedded CSS, JavaScript, and PHP snippets.

<?php 
if( ! function_exists( 'format_code' ) ) {

	function snippet_wrap( $class, $code ) {
		return '' == $code ? '' : '<code class="'.$class.'">'.htmlentities( $code ).'</code>';
	}

	function snippet_php( $open, $code, $close ) {
		return snippet_wrap( 'html', $open ).snippet_wrap( 'php', $code ).snippet_wrap( 'html', $close );
	}

	function php_inside_html( $matches ) {
		list( $all, $before, $open, $code, $close ) = $matches;

		if( '' == $open ) 
			return snippet_wrap( 'html', $all );
		else 
			return snippet_wrap( 'html', $before ).snippet_php( $open, $code, $close );
	}

	function php_inside_css( $matches ) {
		list( $all, $before, $open, $code, $close ) = $matches;

		if( '' == $open ) 
			return snippet_wrap( 'css', $all );
		else 
			return snippet_wrap( 'css', $before ).snippet_php( $open, $code, $close );
	}

	function php_inside_javascript( $matches ) {
		list( $all, $before, $open, $code, $close ) = $matches;

		if( '' == $open ) 
			return snippet_wrap( 'javascript', $all );
		else 
			return snippet_wrap( 'javascript', $before ).snippet_php( $open, $code, $close );
	}

	function php_inside( $class, $code ) {
		return preg_replace_callback( '/(?:(.*?)(\<\?php\s)(.*?)(\?\>))|(?:.+)/si', "php_inside_$class", $code );
	}

	function snippet_web( $class, $open, $code, $close ) {
		return snippet_wrap( 'html', $open ).php_inside( $class, $code ).snippet_wrap( 'html', $close );
	}

	function format_code( $matches ) {
		list( $all, $before, $open, $tag, $code, $close ) = $matches;

		if( '' == $open ) {
			return php_inside( 'html', $all );
		}
		else {
			switch( $tag ) {
				case 'script': $class = 'javascript'; break;
				case 'style' : $class = 'css';        break;
				default      : $class = 'html';
			}
			return php_inside( 'html', $before ).snippet_web( $class, $open, $code, $close );
		}
	}

	function format_clean( $out ) {
		do {
			$len = strlen( $out );
			$out = preg_replace( '/(\<code class="(\w+)"\>[^<]*)\<\/code\>\<code class="\2"\>/is', '$1', $out );
		} while( $len != strlen( $out ) );
		return $out;
	}
}

?>
<pre class="chili-<?php 
	$tmp = preg_split( '/(?:\r?\n)+/', $this->result );
	if( count( $tmp ) > 28 ) echo 'clip';
	else echo 'all'; 
?>"><?php

	$out = preg_replace_callback( '/(?:(.*?)(\<(script|style)\b.*?\>)(.*?)(\<\/\3\>))|(?:.+)/is', 'format_code', $this->result );
	echo format_clean( $out );
?></pre>

The WordPress file /wp-content /themes /default /comments-popup.php is a page that uses all the supported languages, so it’s a good test for the previous template:

<?php

/* Don't remove these lines. */
add_filter('comment_text', 'popuplinks');
while ( have_posts()) : the_post();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
     <title><?php echo get_option('blogname'); ?> - Comments on <?php the_title(); ?></title>

	<meta http-equiv="Content-Type" content="<?php bloginfo('html_type'); ?>; charset=<?php echo get_option('blog_charset'); ?>" />
	<style type="text/css" media="screen">
		@import url( <?php bloginfo('stylesheet_url'); ?> );
		body { margin: 3px; }
	</style>

</head>
<body id="commentspopup">

<h1 id="header"><a href="" title="<?php echo get_option('blogname'); ?>"><?php echo get_option('blogname'); ?></a></h1>

<h2 id="comments">Comments</h2>

<p><a href="<?php echo get_option('siteurl'); ?>/wp-commentsrss2.php?p=<?php echo $post->ID; ?>"><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a></p>

<?php if ('open' == $post->ping_status) { ?>
<p>The <abbr title="Universal Resource Locator">URL</abbr> to TrackBack this entry is: <em><?php trackback_url() ?></em></p>
<?php } ?>

<?php

// this line is WordPress' motor, do not delete it.
$commenter = wp_get_current_commenter();
extract($commenter);
$comments = get_approved_comments($id);
$post = get_post($id);
if (!empty($post->post_password) && $_COOKIE['wp-postpass_'. COOKIEHASH] != $post->post_password) {  // and it doesn't match the cookie
	echo(get_the_password_form());
} else { ?>

<?php if ($comments) { ?>
<ol id="commentlist">
<?php foreach ($comments as $comment) { ?>
	<li id="comment-<?php comment_ID() ?>">
	<?php comment_text() ?>
	<p><cite><?php comment_type('Comment', 'Trackback', 'Pingback'); ?> by <?php comment_author_link() ?> — <?php comment_date() ?> @ <a href="#comment-<?php comment_ID() ?>"><?php comment_time() ?></a></cite></p>
	</li>

<?php } // end for each comment ?>
</ol>
<?php } else { // this is displayed if there are no comments so far ?>
	<p>No comments yet.</p>
<?php } ?>

<?php if ('open' == $post->comment_status) { ?>
<h2>Leave a comment</h2>
<p>Line and paragraph breaks automatic, e-mail address never displayed, <acronym title="Hypertext Markup Language">HTML</acronym> allowed: <code><?php echo allowed_tags(); ?></code></p>

<form action="<?php echo get_option('siteurl'); ?>/wp-comments-post.php" method="post" id="commentform">
	<p>
	  <input type="text" name="author" id="author" class="textarea" value="<?php echo $comment_author; ?>" size="28" tabindex="1" />
	   <label for="author">Name</label>
	<input type="hidden" name="comment_post_ID" value="<?php echo $id; ?>" />
	<input type="hidden" name="redirect_to" value="<?php echo attribute_escape($_SERVER["REQUEST_URI"]); ?>" />
	</p>

	<p>
	  <input type="text" name="email" id="email" value="<?php echo $comment_author_email; ?>" size="28" tabindex="2" />
	   <label for="email">E-mail</label>
	</p>

	<p>
	  <input type="text" name="url" id="url" value="<?php echo $comment_author_url; ?>" size="28" tabindex="3" />
	   <label for="url"><abbr title="Universal Resource Locator">URL</abbr></label>
	</p>

	<p>
	  <label for="comment">Your Comment</label>
	<br />
	  <textarea name="comment" id="comment" cols="70" rows="4" tabindex="4"></textarea>
	</p>

	<p>
	  <input name="submit" type="submit" tabindex="5" value="Say It!" />
	</p>
	<?php do_action('comment_form', $post->ID); ?>
</form>
<?php } else { // comments are closed ?>
<p>Sorry, the comment form is closed at this time.</p>
<?php }
} // end password check
?>

<div><strong><a href="javascript:window.close()">Close this window.</a></strong></div>

<?php // if you delete this the sky will fall on your head
endwhile;
?>

<!-- // this is just the end of the motor - don't touch that line either :) -->
<?php //} ?>
<p class="credit"><?php timer_stop(1); ?> <cite>Powered by <a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art semantic personal publishing platform"><strong>Wordpress</strong></a></cite></p>
<?php // Seen at http://www.mijnkopthee.nl/log2/archive/2003/05/28/esc(18) ?>
<script type="text/javascript">
<!--
document.onkeypress = function esc(e) {
	if(typeof(e) == "undefined") { e=event; }
	if (e.keyCode == 27) { self.close(); }
}
// -->
</script>
</body>
</html>

Chili & Enzymes confirm to be a perfect match.


Next Page »