В основном, когда мы сокращаем/усекаем текстовый контент, мы обычно просто обрезаем его по конкретному индексу символов. Это уже слишком сложно в HTML, но я хочу урезать свой HTML-контент (сгенерированный с помощью редактируемого контента div
) с использованием различных мер:
- Я бы определил индекс символа
N
, который будет использоваться как начальная точка усечения limit - Алгоритм проверяет, имеет ли контент не менее
N
символов (только текст, не считая теги); если нет, он просто вернет весь контент - Затем он будет проверять от
N-X
доN+X
позицию символа (только текст) и искать концы узлов блока;X
является предопределенным значением offset и вероятностью примерно отN/5
доN/4
; - Если несколько узлов блока заканчиваются в этом диапазоне, алгоритм выберет тот, который будет ближе всего к пределу индекса
N
- Если в этом диапазоне не заканчивается блок node, он найдет ближайшую границу слова в пределах того же диапазона и выберите индекс, ближайший к
N
, и усечет в этой позиции. - Возвращает усеченное содержимое с допустимым HTML (все теги закрыты в конце)
Мое содержимое, редактируемое для контента, может состоять из абзацев (с разрывами строк), предварительно отформатированных блоков кода, кавычек блоков, упорядоченных и неупорядоченных списков, заголовков, полужирных и курсивых (которые являются встроенными узлами и не должны учитываться в процессе усечения) Конечная реализация, конечно, определит, какие элементы конкретно являются возможными кандидатами усечения. Заголовки, даже если они являются блочными элементами HTML, не будут считаться точками усечения, поскольку нам не нужны овдовевшие заголовки. Пункты, список отдельных элементов, целые упорядоченные и неупорядоченные списки, блок-кавычки, предварительно отформатированные блоки, элементы пустот и т.д. Являются хорошими. Заголовки и все встроенные элементы блока не являются.
Пример
Возьмем этот самый вопрос stackoverflow как пример содержимого HTML, который я хотел бы усечь. Пусть установлен предел усечения 1000 со смещением символов 250 (1/4).
Этот DotNetFiddle показывает текст этого вопроса, а также добавляет в него ограничивающие маркеры (|MIN|
, который представляет символ 750, |LIMIT|
, представляющий символ 1000 и |MAX|
, который представляет символ 1250).
Как видно из примера , ближайшая граница усечения между двумя блочными узлами для символа 1000 находится между </OL>
и P
(My content-editable generated...). Это означает, что мой HTML-код должен быть усечен прямо между этими двумя тегами, что приведет к содержанию текста с текстом чуть меньше 1000 символов, но содержало усеченный контент значимым, потому что он не просто усекал бы где-нибудь посередине некоторого текстового прохода.
Надеюсь, это объяснит, как нужно работать над этим алгоритмом.
Проблема
Первая проблема, которую я вижу здесь, заключается в том, что я имею дело с вложенной структурой, такой как HTML. Я также должен обнаруживать разные элементы (только элементы блока и не встроенные). И последнее, но не в последнюю очередь, мне придется только подсчитать некоторые символы в моей строке и игнорировать те, которые относятся к тегам.
Возможные решения
- Я мог бы вручную разобрать свой контент, создав некоторое дерево объектов, представляющее узлы контента и их иерархию
- Я мог бы преобразовать HTML в нечто более удобное для управления, например markdown, а затем просто искать ближайшую новую строку для моего предоставленного индекса
N
и конвертировать обратно в HTML - Используйте что-то вроде HTML Agility Pack и замените мой синтаксический анализ # 1, а затем каким-то образом используйте XPath для извлечения узлов блока и усечения содержимого
Вторые мысли
- Я уверен, что смогу сделать это, заняв # 1, но мне кажется, что я изобретаю колесо.
- Я не думаю, что есть библиотека С# для # 2, поэтому я должен делать HTML для Markdown вручную или запускать i.e.pandoc как внешний процесс.
- Я мог бы использовать HAP, поскольку он отлично справляется с управлением HTML, но я не уверен, будет ли мое усечение достаточно простым, используя его. Я боюсь, что основная часть обработки будет по-прежнему находиться вне HAP в моем пользовательском коде.
Как следует подходить к таким алгоритмам усечения? Моя голова кажется слишком усталой, чтобы прийти к консенсусу (или решению).