Mar 18 2008

Metaobjects 1.5 Released

Tag: MetaobjectsAndrea Ercolino @ 23:10:23
Changes
  • Added support for easy namespacing
  • Added support for jQuery 1.2.3 cache
  • Rewritten the manual from scratch
Download

You can download metaobjects from Google Code


Feb 22 2007

How to Share Source Code using Chili in IE

Tag: Chili, MetaobjectsAndrea Ercolino @ 11:14:03

I’ve recently realized that copying to the clipboard a snippet highlighted by Chili works differently in Internet Explorer (IE) and in Mozilla Firefox (FF). They both copy two versions of the selected section: TEXT and HTML.

IE TEXT
HTML entities resolved
HTML stripped off
result copied
FF TEXT
HTML entities resolved
BR elements replaced by new lines
HTML stripped off
result copied
IE HTML
HEAD element copied
containment path elements copied
selected text with HTML in place copied
FF HTML
selected text with HTML in place copied

The net result of all this is that IE does the right thing with HTML while FF does the right thing with TEXT, and neither is completely right or wrong.

  • copying from IE to Notepad you get an awful long line, but copying to Word you get all wonderfully colored
  • copying from FF to Notepad you get a properly formatted section, but copying to Word you get all sadly monochromatic

UPDATE (2007/02/24): What follows is obsolete, because I’ve implemented a transparent method in Chili 1.7

In Chili 1.6 I’ve implemented a workaround for IE, so that IE TEXT is like FF TEXT. It’s a workaround because you need to add a button to each highlighted section, and it will copy all the text in that section when clicked.

The button can be as simple as a DIV placed before the PRE, like this:

<div class="ie_copy" title="copy this snippet to the clipboard">
copy all
</div>
<pre><code class="javascript">
alert( "Hello World!" );
</code></pre>

Chili will hide any element with a class ie_copy in any browser but IE, where instead it will associate a click handler to it, for copying all the next PRE content as a properly formatted section. You can style the button element as you like, because Chili uses the class only for accessing the element.

You can also place the button wherever you like. If so, i.e. if the button element is not the element preceding the PRE section, then you have to feed Chili the method for getting the PRE content. You can do it globally or locally.

When Chili associates the handler to the button, it will look for a getPRE method inside the button element. If there is one, then it will be used, else Chili will look for a getPRE method inside the global ChiliBook object. If there is one, then it will be used, else Chili will give up and not associate a handler.

You can change the global behavior by changing the declaration of the getPRE method inside the ChiliBook object, and you can change the local behavior by adding a chili metaobject (an object with a class chili) inside the button element, with a getPRE param whose value is the function declaration.

The getPRE function shipped with Chili 1.6 is the following, where the button element is passed into this and the PRE destination is found starting from that origin:

function() { return $( this ).next( "pre" )[0]; }

A button element after the PRE element could then be locally configured like this:

<pre><code class="javascript">
alert( "Hello World!" );
</code></pre>
<div class="ie_copy" title="copy this snippet to the clipboard">
<object class="chili">
	<param name="getPRE" value="function() { return $( this ).prev( 'pre' )[0]; }"/>
</object>
copy all
</div>


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 »