Уменьшите html до n символов, сохраняя при этом форматирование

11

Почти в каждом языке есть встроенная функция, которая может разбивать строку в заданной позиции. Однако, как только в строке есть html-теги, встроенная функция не будет работать должным образом.

Ваша задача - написать программу или функцию, которая разбивает строку на n-й символ, но не считает символы тегов html и выведет действительный html. Программа должна сохранять форматирование. Пробелы за пределами HTML-тегов могут быть подсчитаны или не подсчитаны, как вы хотите, но должны быть сохранены. Однако вы можете заменить несколько последовательных пробелов в один пробел.

Входные данные:

  1. Струна
  2. позиция для разделения (на основе 0)

Они могут быть приняты в качестве аргументов программы или функции или могут быть прочитаны из стандартного ввода.

Вывод: Разделенная строка, которая может быть возвращена или записана в стандартный вывод.

Ввод будет действительным html, он не будет содержать никаких объектов (таких как  ). Теги, которые открываются после ограничения количества символов, должны быть опущены в выводе (см. Последний пример).

Пример:

Входной сигнал: <i>test</i>3
Выход:<i>tes</i>

Вход: <strong><i>more</i> <span style="color: red">complicated</span></strong>7
Выход:<strong><i>more</i> <span style="color: red">co</span></strong>

Вход: no html2
Выход:no

Вход: <b>no</b> <i>html root</i>5
Выход:<b>no</b> <i>ht</i>

Вход: <b>no img</b><img src="test.png" />more text6
Выход:<b>no img</b>

Вы можете использовать любой язык и стандартную библиотеку данного языка. Это код гольфа, самая короткая программа выигрывает. Повеселись!

Дэвид Франк
источник
1
входные данные могут содержать «<» и «>», которые не являются частью тега HTML?
xem
Нужно использовать &lt;и &gt;вместо <>, так что нет ( &lt;или &gt;не будет присутствовать либо).
Дэвид Франк
Не могли бы вы включить пример, где после текстового узла есть разметка, где происходит разделение? Как <i>ab</i><b>cd</b> 1?
Мартин Эндер
Есть ли другие варианты, кроме <i>a</i>?
Дэвид Франк
@DavidFrank <i>a</i><b></b>(что имеет смысл, если вы считаете, что это bтакже может быть divили img.)
Мартин Эндер

Ответы:

2

Этот ответ больше не действует с последним правилом.

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
источник
Не могли бы вы предоставить код для игры в гольф или просто объяснение того, что и почему делает код? В настоящее время его немного сложно понять. Благодаря!
Гауранг Тандон
@GaurangTandon добавил код без комментариев с комментариями
nderscore
2

Реболь - 252 символа

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])]]]]

Разоблаченный с комментариями:

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]
                )
            ]
        ]
    ]
]

Примеры в консоли 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
источник
Это снова нарушает последнее правило: теги, которые открываются после ограничения на количество символов, должны быть опущены в выводе (см. Последний пример). В последнем примере теги span и b должны быть опущены. Это правило делает задачу практически невозможной.
edc65
@ edc65 - К сожалению (@David Frank) не прокомментировал и не обновил свои примеры, поэтому неясно, хочет он этого поведения или нет? Я надеялся, что мой последний пример будет что-то мешать! Собираюсь оставить как есть, пока не получим разъяснения. В любом случае, потребуется всего 17 дополнительных символов, чтобы все работало так, как вы предлагали. Мне не особо понравился этот хак, поэтому я переписал его здесь (без гольфа) - gist.github.com/draegtun/93682f5a07c40bd86e31
draegtun
0

Рубин ... Очень непохож на петли

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
источник
Этот вопрос помечен как codegolf, вы должны ответить на ваш вопрос. Вы можете начать с замены имен переменных на имена,
состоящие из
0

(IE) 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}

Теперь я чувствую себя грязным. Но нужно начать удалять все эти символы ...

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

Отказ от ответственности:

  • запустить в консоли IE
eithed
источник
1
Это нарушает последнее (безумное) правило: теги, которые открываются после ограничения количества символов, должны быть исключены из вывода (попробуйте мой пример в комментариях выше).
edc65
@ edc65, надеюсь, обновленная версия проверяет все правила
вышла