Adicionar ícone a links externos, MAS não âncoras que contêm uma imagem

O problema

Eu tinha um site que criava links externos com CSS bastante simples. Você já viu esse padrão antes, aposto. Para fins ilustrativos, é isso:

a[href^="http:"]:before:not([href^="http://www.thissite.com"]), 
a
[href^="https:"]:before {
...icon styles...
}

Funcionou bem, mas havia um problema. O cliente adicionou âncoras ao redor das imagens, o que é perfeitamente aceitável (e algo que eu deveria ter esperado) e então, quando a imagem estava bonita e grande, ela tinha um ícone à esquerda. Não parecia bom e eu concordei. Eu tive que consertar isso.

CSS não fornecerá uma solução

O problema é que não existe um seletor CSS que possa me ajudar a excluir esse estilo quando um acontém um img. O seletor a > imgou a + imgo estilizará img, o que não me ajudará. O que realmente precisamos é de um a < imgseletor, mas ele não existe (até Chris Coyler deseja que sim, sem sorte .

Felizmente, temos o jQuery que pode ajudar.

Fiquei surpreso por não ter conseguido encontrar outra pessoa que tivesse feito exatamente o que eu procurava. Após algumas pesquisas, alguns testes e algumas investigações sobre a extensão agradável has () jQuery, decidi por esta solução (compatível com jQuery 1.1.4 e superior):

/* Add rel="external" to links that are external (this.hostname !== location.hostname) BUT don't add to anchors containing images */
$
('.text a').each(function() {
// Compare the anchor tag's host name with location's host name
return this.hostname && this.hostname !== location.hostname;
}).not('a:has(img)').attr("rel","external");

NOTA: Eu uso ‘.texto a’ para aplicar este atributo apenas a âncoras na área de conteúdo principal, o que evita percorrer links na navegação e outros lugares aos quais não desejo os ícones se aplicarem.

Em vez de adicionar uma classe, decidi adicionar um atributo que seria útil para SEO e semântica. Em seguida, estilizo essa classe com um seletor de atributos CSS simples:

a[rel=external]:before {
...icon styles...
}

Também decidi não acrescentar , embora pudesse facilmente. O motivo é que o cliente tem um CMS com um editor WYSIWYG e, portanto, eles têm controle sobre a adição ou não de um destino. Para mim, era melhor deixar essas coisas sob seu controle e usar o jQuery para fazer automaticamente as coisas que melhoram a experiência do usuário final.target="_blank"