Tamara asked on the Blosxom mailing list if my macros plugin was capable of making external links open in new windows like this.

My first answer was no -- it's missing two features that that uses, <MTIfMatches> and MTMacros' 'rebuild'. Furthermore, I don't really think MTIfMatches belongs in macros; it's a better fit for a somewhat fancier interpolate-conditional.

I'm not sure how exactly MTMacros' 'rebuild' works, and it may well be a useful feature to steal borrow...I should look at that.

I realized this morning that there is in fact a way, though; it's not quite as clean as Adam Kelsey's, since it's simply text based rather than tag-based, but it seems to work just fine.

The magic is in these macros (use the download link to get a good straight-text version):

define_macro({
  type => 'pattern',
  pattern => qr'<a\s(?![^>]*class)([^>]*href="/)'ms,
  body => '<a class="relative" ${1}',
  inhtml => 1
});

That looks for 'a' tags that don't have a 'class' attribute, with an 'href' attribute that starts with a slash, and adds a 'class="relative"' attribute.

define_macro({
  type => 'pattern',
  pattern => qr'<a\s(?![^>]*class)([^>]*href="http://[^/]*molehill\.org[:/])'ms,
  body => '<a class="local" ${1}',
  inhtml => 1
});

That looks for 'a' elements that don't have a 'class' attribute, with an 'href' attribute that starts with an a "http://", and has my domain name before the next / or :, and gives them a 'class="local"' attribute.

define_macro({
  type => 'pattern',
  pattern => qr'<a\s(?![^>]*class)([^>]*href)'ms,
  body => '<a class="remote" ${1}',
  inhtml => 1
});

That looks for 'a' elements that don't have a 'class' attribute, but do have an 'href' attribute (that prevents it from applying to anchors used just for naming); and gives them a 'class="remote"' attribute; that's right, since every non-remote link has been given a 'local' or 'relative' class.

I'm also using some stylesheet magic:

a.remote {
	padding-right:		12px;
	background-image:	url(/icon/aoutside.gif);
	background-position:	right;
	background-repeat:	no-repeat;
}

and an icon apparently from WebGragpics.

I didn't add "target" attributes, but it should be clear how to do that -- simply put them before the 'class' in the replacement text.

As I said, this isn't quite as clean, and it's not 100% correct -- the word "class" in an href could confuse it, for instance. But it's pretty close, and it's doable now. (it could be improved by replacing the (?![>]*class)s with (?![>]*\bclass=")s, but that still wouldn't be 100% right, and I wanted to present what I'm actually using and have tested).

Sorry, comments are currently disabled. They'll be returning shortly, if all goes according to plan.