Reduza html para n caracteres enquanto mantém a formatação

11

Quase todos os idiomas possuem uma função integrada que pode dividir uma string em uma determinada posição. No entanto, assim que você tiver tags html na string, a função interna não funcionará corretamente.

Sua tarefa é escrever um programa ou função que divida uma string no enésimo caractere, mas não conta os caracteres das tags html e produzirá um html válido. O programa deve manter a formatação. Os espaços fora das tags html podem ser contados ou não, conforme desejado, mas devem ser preservados. No entanto, você pode trocar vários espaços consecutivos em um único espaço.

Entrada:

  1. a corda
  2. a posição para dividir em (com base em 0)

Eles podem ser tomados como argumentos de programa ou função ou podem ser lidos a partir da entrada padrão.

Saída: a cadeia de caracteres dividida que pode ser retornada ou gravada na saída padrão.

A entrada será um html válido, não conterá nenhuma entidade (como  ). As tags que são abertas após o limite de caracteres devem ser omitidas da saída (consulte o último exemplo).

Exemplo:

Entrada :, <i>test</i>3
Saída:<i>tes</i>

Entrada :, <strong><i>more</i> <span style="color: red">complicated</span></strong>7
Saída:<strong><i>more</i> <span style="color: red">co</span></strong>

Entrada :, no html2
Saída:no

Entrada :, <b>no</b> <i>html root</i>5
Saída:<b>no</b> <i>ht</i>

Entrada :, <b>no img</b><img src="test.png" />more text6
Saída:<b>no img</b>

Você pode usar qualquer idioma e a biblioteca padrão do idioma especificado. Este é o código de golfe, o programa mais curto vence. Diverta-se!

David Frank
fonte
1
a entrada pode conter "<" se ">" s que não fazem parte de uma tag HTML?
Xem
Deve-se usar &lt;e, em &gt;vez de <>, então não ( &lt;ou &gt;não estará presente também).
David Frank
Você poderia incluir um exemplo em que há marcas após o nó de texto em que a divisão ocorre? Gosta <i>ab</i><b>cd</b> 1?
Martin Ender
Existem outras opções além disso <i>a</i>?
David Frank
@DavidFrank <i>a</i><b></b>(que faz sentido se você considerar que btambém poderia ser divou img.)
Martin Ender

Respostas:

2

Esta resposta não é mais válida com a regra mais recente.

Javascript ( ES6 ) 94 91

f=(s,l)=>s.split(/(<[^>]+>)/).map(x=>x[0]=='<'?x:[l-->0?y:''for(y of x)].join('')).join('')
f('<strong><i>more</i> <span style="color: red">complicated</span></strong>', 7);
// '<strong><i>more</i> <span style="color: red">co</span></strong>'

Ungolfed:

f=(s,l)=>
    s.split(/(<[^>]+>)/). // split string s by <*>, capture group is spliced into the array 
    map(x=> // map function to every item in the array
        x[0]=='<'? // if first character is a <
            x // don't modify the string
        : // else
            [ // array comprehension
                for(y of x) // for every character y in x
                    l-->0? // if l > 0 (and decrement l)
                        y // character y
                    : // else
                        '' // empty string 
            ].join('') // join characters in array
        ).
    join('') // join all strings in array
nderscore
fonte
Você poderia, por favor, fornecer o código não golfe, ou talvez apenas uma explicação sobre o que e por que o código funciona? Atualmente é um pouco difícil de entender. Obrigado!
Gaurang Tandon
@GaurangTandon adicionou código não destruído com comentários
nderscore
2

Rebol - 252 caracteres

c: complement charset"<>"f: func[s n][t: e: 0 to-string collect[parse s[any[(m: 0)copy w[["</"some c">"](-- t)|["<"some c"/>"]|["<"some c">"](++ t)| any c(m: 1)](if e = 0[if m = 1[w: copy/part w n n: n - length? w]keep w]if all[n <= 0 t = 0][e: 1])]]]]

Ungolfed com comentários:

c: complement charset "<>"

f: func [s n] [
    t: e: 0             ;; tag level (nesting) & end output flag
    to-string collect [
        parse s [
            any [
                (m: 0)                            ;; tag mode
                copy w [
                      ["</" some c ">" ] (-- t)   ;; close tag
                    | ["<"  some c "/>"]          ;; self-closing / void elements
                    | ["<"  some c ">" ] (++ t)   ;; open tag
                    | any c (m: 1)                ;; text mode
                ] (
                    ;; flag not set so can still output
                    if e = 0 [
                        ;; in text mode - so trim text
                        if m = 1 [
                            w: copy/part w n
                            n: n - length? w
                        ]
                        keep w
                    ]

                    ; if all trimmed and returned to flat tag level then end future output
                    if all [n <= 0  t = 0] [e: 1]
                )
            ]
        ]
    ]
]

Exemplos no console Rebol:

>> f "<i>test</i>" 3
== "<i>tes</i>"

>> f {<strong><i>more</i> <span style="color: red">complicated</span></strong>} 7
== {<strong><i>more</i> <span style="color: red">co</span></strong>}

>> f {no html} 2
== "no"

>> f {<b>no</b> <i>html root</i>} 5
== "<b>no</b> <i>ht</i>"

>> f {<b>no img</b><img src="test.png" />more text} 6
== "<b>no img</b>"

>> f {<i>a</i><b></b>} 1
== "<i>a</i>"

>> f {<strong><i>even</i> <span style="color: red">more <b>difficult</b></span></strong>} 14
== {<strong><i>even</i> <span style="color: red">more <b>diff</b></span></strong>}

>> f {<strong><i>even</i> <span style="color: red">more <b>difficult</b></span></strong>} 3 
== {<strong><i>eve</i><span style="color: red"><b></b></span></strong>}
draegtun
fonte
Novamente, isso quebra a última regra: as tags que são abertas após o limite de caracteres devem ser omitidas na saída (veja o último exemplo). No último exemplo, as tags span e b devem ser omitidas. Essa regra torna o desafio quase impossível.
edc65
@ edc65 - Infelizmente (@ David Frank) não comentou ou atualizou seus exemplos, então não está claro se ele quer esse comportamento ou não? Eu esperava que meu último exemplo mexesse alguma coisa! Vamos sair como estão até obtermos esclarecimentos. De qualquer forma, seriam necessários apenas 17 caracteres adicionais para que funcionasse da maneira sugerida. Eu não fiz particular, como o hack então ao invés reescreveu-lo aqui (ungolfed) - gist.github.com/draegtun/93682f5a07c40bd86e31
draegtun
0

Ruby ... Muito unrubylike com loops

def split(str,n)

  i = current = 0 
  return_str = ""

  while i < n
    if str[current] == "<"
      while str[current] != ">"
        return_str.concat str[current]
        current += 1
      end
      return_str.concat str[current]
      current += 1
    else
      return_str.concat str[current]
      i += 1
      current += 1
    end
  end

  while current < str.length
    if str[current] == "<"
      while str[current] != ">"
        return_str.concat str[current]
        current += 1
      end
      return_str.concat str[current]
      current += 1
    end
    current += 1
  end


  return_str + str[current..-1]
end
user26900
fonte
Esta pergunta está marcada como codegolf, você deve responder com a sua resposta. Você pode começar por substituir os nomes de variáveis para um nome das letras, usando nomes de função mais curtos e removendo espaço em branco, sempre que puder
sagiksp
0

JS - 135

function f(t,n){b=document.body;b.innerHTML=t;r=b.createTextRange();r.moveStart("character",n);r.select();r.execCommand('cut');return b.innerHTML}

Agora me sinto sujo. Mas precisa começar a remover todos esses caracteres ...

function f(t,n)
{b=document.body;b.innerHTML=t;r=b.createTextRange();r.collapse();r.moveEnd("character",n);
r.select();return r.htmlText}

Aviso Legal:

  • executar no console do IE
eithed
fonte
1
Isso quebra a última regra (louca): as tags que são abertas após o limite de caracteres devem ser omitidas na saída (tente meu exemplo nos comentários acima).
Edc65
@ edc65, esperançosamente, a versão atualizada verifica todas as regras
encerrada em 6/07/14