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).
It would be more correct without the extraneous classes, since those aren’t used for this purpose. All the same, thanks for figuring that out for me.
It could be done without the extra classes, but it would need a more complicated regular expression to recognize offsite links.
define_macro({
type => ‘pattern’,
pattern => qr’<a\s(?![>]*class)([^>]*href://(?![/]*molehill.org[:/]))’ms,
body => ‘<a class=”remote” ${1}’,
inhtml => 1
});
would do it (for molehill.org, of course), I think. That’s not tested.
It makes sense to me to class them all, though, even if you’re not using the other classes right now — you may well want to later, and users might want to with user stylesheets.
Sorry, comments are currently disabled. They'll be returning shortly, if all goes according to plan.