As motivações das perguntas foram descritas na seção abaixo. Existem várias maneiras de colocar o texto em itálico ; portanto, talvez haja mais de um bom " algoritmo de troca de itálico ". O problema revela algumas dificuldades adicionais em um código XHTML, e o uso da <i>
tag deve ser equilibrado . Exemplo:
<!-- original text: -->
<p id="p1"><i>Several more</i> Homo sapiens <i>fossils were discovered</i>.</p>
<!-- same text, swapping italics: -->
<p id="p2">Several more <i>Homo sapiens</i> fossils were discovered.</p>
Então, fica assim,
Vários outros fósseis do Homo sapiens foram descobertos .
Vários outros fósseis do Homo sapiens foram descobertos.
Introdução e discussão de algoritmos
Para " solução de layout ", o algoritmo mais simples é verificar a font-style
propriedade CSS de todos os blocos de texto e invertê-los com jQuery:
$('#myFragment *').each(function(){
if ($(this).css('font-style')=='italic')
$(this).css('font-style','normal')
else
$(this).css('font-style','italic')
});
Mas esse algoritmo não sobrevive a um teste um pouco mais complexo,
<p id="p3"><b><i>F</i>RAGMENT <big><i>with italics</i> and </big> withOUT.</b></p>
O segundo algoritmo mais simples é para uma solução concreta e foi usado na seção "Exemplos". Tenha duas etapas:
- coloque o fragmento XHTML em itálico;
- inverter abrir / fechar tags em itálico (por exemplo,
</i>
para<i>
).
Ou seja, escrevendo com Javascript,
var s = '... a fragment of XHTML content ...';
s = '<i>'+
s.replace(/<(\/?)i>/mg,
function (m,p1){
return p1? '<i>': '</i>';
}
) +
'</i>';
Mas também não sobrevive ao segundo teste, perdendo o equilíbrio de tags ... O algoritmo "corrigido" é executado (!), Mas não é portátil, nem rápido nem elegante. É demonstrado aqui e na seção de exemplo abaixo.
O ponto!
Então a questão é:
existe um algoritmo simples, bom e genérico (utilizável em qualquer navegador e portátil para outros idiomas)? Você conhece outro "algoritmo de troca de itálico"?
PS: "genérico" no sentido em que eu até traduzo seu algoritmo para XSLT. O algoritmo deve produzir código XHTML balanceado diretamente (sem uma caixa preta intermediária como o Tidy).
Motivações
Preciso portar o "algoritmo de troca de itálico" para editores de texto, analisadores de servidor, etc. Em todos os casos, posso "normalizar a entrada" (e a saída) pelo XHTML e <i>
tag padrão .
Estou analisando o texto XHTML de livros de prosa e artigos científicos, exportados de diferentes origens e estilos ... A maioria dos textos é exportada como "texto normal", mas muitos títulos (por exemplo, título do artigo, título do capítulo) e, às vezes , um capítulo completo ou uma caixa de texto completa (por exemplo, resumo do artigo) são estilizados em itálico. Todos estes "estilizados com itálico" devem ser invertidos. Casos típicos:
Transforme o "todos os capítulos em itálico" em "todos os capítulos em texto normal": veja este caso , onde em um livro de aproximadamente 300 páginas, 8 dos 25 capítulos precisam ser invertidos.
Aspas em itálico, resumos, etc. Veja este exemplo . Precisa voltar ao normal, mas sem perder as palavras de ênfase.
Escrever nomes binomiais de espécies , em textos científicos, geralmente é digitado em itálico (ou invertido, em uma fonte diferente daquela usada para o "texto normal"). Centenas de títulos em itálico (de artigos e de seções de artigos) de artigos exportados em XHTML devem ser invertidos no meu local de trabalho. PS: veja o exemplo do início da pergunta ("Vários mais Homo sapiens ...").
Também preciso traduzir o algoritmo genérico (da sua resposta!) Em uma biblioteca XSLT , onde não existe uma "correção de balanceamento de tags".
Exemplos
Implementando em Javascript e PHP um "algoritmo de troca de itálico" não genérico . Um genérico precisa de um "algoritmo de intercalação XML" geral ... Aqui eu uso correções do navegador (DOM) e Tidy, como uma alternativa à "intercalação".
Javascript
É executado com entradas complexas (!). Ilustrando, por uma implementação do jQuery :
var s = $('#sample1').html(); // get original html text fragment
// INVERSION ALGORITHM: add and remove italics.
s = "<i>"+
s.replace(/<(\/?)i>/mg,
function (m,p1){
return p1? '<i>': '</i>';
}
) +
"</i>"; // a not-well-formed-XHTML, but it is ok...
$('#inverted').html(s); // ...the DOM do all rigth!
// minor corrections, for clean empties:
s = $('#inverted').html();
s = s.replace(/<([a-z]+)>(\s*)<\/\1>/mg,'$2'); // clean
s = s.replace(/<([a-z]+)>(\s*)<\/\1>/mg,'$2'); // clean remain
$('#inverted').html(s);
// END ALGORITHM
alert(s);
PHP, com arrumado
O mesmo de Javascript, "traduzido" para PHP - a tradução natural está usando DOMDocument()
classe e loadHTML
/ saveXML
methodos, mas o que tem o mesmo comportamento que os correspondentes do navegador é a tidy
classe . Mostra os mesmos resultados (!)
$sample1='<b><i>O</i>RIGINAL <big><i>with italics</i> and </big> withOUT</b>';
$inverted = '... inverted will be here ...';
echo $sample1;
// Tidy correction
$s = $sample1; // get original html text fragment
// INVERSION ALGORITHM: add and remove italics.
$s = "<i>".
preg_replace_callback('/<(\/?)i>/s', function ($m){
return $m[1]? '<i>': '</i>';}, $s) .
"</i>"; // a not-well-formed-XHTML, but it is ok...
$config = array('show-body-only'=>true,'output-xhtml'=>true);
$tidy = new tidy;
$tidy->parseString($s, $config, 'utf8');
$s = $tidy; // ... because Tidy corrects!
// minor corrections, for clean empties:
$s = preg_replace('/<([a-z]+)>(\s*)<\/\1>/s', '$2', $s); // clean
$s = preg_replace('/<([a-z]+)>(\s*)<\/\1>/s', '$2', $s); // clean remain
// END ALGORITHM
echo "\n\n$s";
fonte
Respostas:
Atualização (18 de junho de 13): use esta resposta para explicar algoritmos e resumir conclusões.
Sobre as soluções alternativas de deslocamento e "solução de layout" do jQuery.
Após o comentário do @Wilbert, adaptei o "algoritmo mais simples", para evitar o comportamento dinâmico do
check .prop()
, que muda com a.each()
iteração, removendo oelse
. Após toda a iteração, um "itálico pai" é resolvido. Veja aqui ou o código abaixo.Outra maneira de lidar com o comportamento dinâmico é verificar uma propriedade estática
prop('tagName')
, que não muda. Veja aqui ou o código abaixo.Ele precisa de mais testes e precisa de uma análise final para alterar as propriedades do estilo para
<i>
tags concretas . Para aplicar o algoritmo duas vezes, precisamos de alguns cuidados.Solução de layout
Esta não é uma solução para a presente pergunta, mas produz algumas boas dicas e é a melhor (pelo menos a menor!) Solução para o "problema de layout"!
O
toggleClass()
método pode ser usado para trocar de uma "classe em itálico" para uma "classe de texto normal". Veja aqui ou o código abaixo.E podemos aplicar esse pequeno algoritmo duas vezes e quantas vezes quisermos ... É uma boa solução! Mas não é um "algoritmo de reescrita XML", o CSS é uma chave aqui :
... Então, para um algoritmo que transforma
<i>
tags, o problema ainda está aberto ...Solução de concreto
Uma "solução 100%, em XSLT1 puro" (testada com muitos casos!) Baseada em uma adaptação do @ DanielHaley's . É uma
<i>
transformação eficaz de tags.Esboçando como uma "unidade por algoritmo de evento" em um processo de cópia:
remover
i
tags: copie qualquer coisa de "<i>
coisa</i>
" como " coisa ".inclua
i
tags: copie qualquer texto como "<i>
texto</i>
", quando o texto não estiver em um contexto de pais em itálico. PS: o texto é um nó terminal da árvore DOM.Conclusões
As "soluções de layout" são boas para os editores de texto , mas usam alguns truques e soluções não rigorosas (independentemente de sobreposições, desempenho etc.). Para o processo XML, precisamos lidar com a
<i>
transformação de tags ... Então, as linguagens naturais para expressar o algoritmo são XSLT ou xQuery.O algoritmo implementado com o XSLT mostra as necessidades da estrutura:
o seletor ancestral (pai, avô, etc.), para verificar se é ou não um "contexto em itálico";
o acesso do nó de texto (DOM
text()
);remova e inclua a
i
tag.Assim, podemos ver os problemas com cada estrutura.
DOM (a estrutura padrão do W3C): o
DOMDocument::renameNode()
item 3 ainda não foi implementado (consulte PHP, Javascript, etc.).jQuery: não possui uma função conveniente para o item 2, veja esta resposta .
XSLT: o melhor para expressar o algoritmo, mas não está disponível em nenhum contexto como Javascript.
Eu (ou você, por favor!) Tentarei expressar o algoritmo XSLT com métodos "DOM2 puro". Essa versão do DOM será o "algoritmo genérico" ... Bem: se a tradução for válida apenas para o DOM3 (usando renameNode e outros truques), a conclusão por enquanto é que "não há algoritmo genérico / traduzível".
fonte
XSLT tentativa de https://stackoverflow.com/a/17156452/317052 ...
Não tenho certeza se isso abrangeria todos os casos, mas você poderia fazer isso:
Entrada XML
XSLT 1.0
Saída XML
Entrada renderizada
Vários outros fósseis do Homo sapiens foram descobertos .
Vários outros fósseis do Homo sapiens foram descobertos.Me deixe em paz!
O RIGINAL com itálico e semOUT
Saída renderizada
Vários outros fósseis do Homo sapiens foram descobertos .
Vários outros fósseis do Homo sapiens foram descobertos.Me deixe em paz!
O RIGINAL com itálico e semOUT
fonte
Eu simplesmente:
<i>
em</i>
s</i>
em<i>
s<i>
ao começo</i>
no finalassim
fonte
<b><i>O</i>RIGINAL <big><i>with italics</i> and </big> withOUT</b>
... produz código desequilibrado (proibido!) E blocos vazios .<i><b></i>O<i>RIGINAL <big></i>with italics<i> and </big> withOUT</b></i>
pode não ser Bonito, mas funciona em todos os navegadores #<i><b></i>
não é, e TODA A DISCUSSÃO AQUI é sobre "um algoritmo que produz resultados balanceados".