Реализация предварительного просмотра для текста уценки

Я работаю над проектом Ruby on Rails и реализовал синтаксис уценки для некоторых текстовых описаний в моем проекте, используя redcarpet. драгоценный камень.

Он работает как шарм, позволяя преобразовывать текст уценки в HTML так же просто, как

<%= markdown some_text_variable %>

Но теперь я хочу реализовать функцию предварительного просмотра, отображающую только небольшую часть полного текста.

Следующая наивная конструкция

<%= markdown some_text_variable[0..preview_length] %>

не будет работать, потому что он может легко нарушить синтаксис MD, что приведет к запутанным конструкциям (представьте, например, что исходная строка разбивается на половину ссылки на изображение).

я придумал

<%= markdown some_text_variable[0..preview_length].split(/\r?\n/)[0..-2].join("\r\n")) %>

но это не касается, например, кодовых блоков.

Есть ли способ реализовать такой предварительный просмотр для текста MD?


person zavg    schedule 18.03.2015    source источник
comment
Можете ли вы перебрать массив синтаксиса уценки и проверить регулярное выражение, которое соответствует новой строке и любым символам уценки? Если true (имеет открытие и закрытие), распечатайте фрагмент, а если false (имеет открытие, но не закрывает и не открывает теги до следующего закрытия или новой строки), добавьте закрывающий тег и распечатайте фрагмент?   -  person Bottled Smoke    schedule 18.03.2015
comment
@BottledSmoke Разве это не слишком сложно? А как быть со списками, у которых нет закрывающих тегов? Я придумал просто нарезать на новую строку (но не меньше определенного количества символов). Но это также не касается списков...   -  person zavg    schedule 18.03.2015
comment
Да, я только что понял, что вы можете использовать уценку и шоудаун. Тебе придется простить меня. Я только что проснулся :)   -  person Bottled Smoke    schedule 18.03.2015


Ответы (2)


Использование markdown.js и/или showdown должен работать. Вот StackO с тем же вопросом и ответом. Я лично использовал showdown в приложении Ember, прежде чем отображать предварительный просмотр текста в режиме реального времени по мере его ввода (через двустороннюю привязку данных), и он работал безупречно.

В скрипке ниже я написал небольшой анализатор Showdown, который принимает строку уценки, разбивает ее на новую строку (возвращает массив тегов) и выполняет итерацию по массиву. На каждой итерации он удаляет теги, проверяет длину результирующей строки, а затем сравнивает ее с максимальным количеством символов для предварительного просмотра. Как только следующая итерация превысит максимальное количество символов, она вернет предварительный просмотр. Цикл do гарантирует, что вы всегда получите хотя бы один блок html в качестве предварительного просмотра.

Скрипка

$(function() {
  var converter = new Showdown.converter();
  var previewMax = 200;

  $('button').click(function() {        
    var content = $('#markdown').val(),
        charCount = 0,
        i = 0,
        output = '';

    if (!content) {
      return $('div.preview').html("Please enter some text.");
    }

    var mark = converter.makeHtml(content);
    var mark_arr = mark.split('\n');

    while (charCount < previewMax) {
      var html = mark_arr[i];
      var text = htmlStrip(html);            

      if ((charCount + text.length) > previewMax) {
        var overflow = (charCount + text.length) - previewMax;
        var clipAmount = text.length - overflow;
        html = jQuery.truncate(mark_arr[i], { length: clipAmount });
        }

      output += html;
      charCount += text.length;
      i++;
    };

    $('div.preview').html(output);
    $('div.full').html(mark);
  });

  function htmlStrip (html) {
    var div = document.createElement('div');
    div.innerHTML = html;
    var text = div.textContent || div.innerText || "";
    return text;
  }
});

ПЕРЕСМОТР

Я обновил функцию, используя jQuery Truncate, чтобы разрезать окончательную строку на многоточие, чтобы все ваши предварительные просмотры были той же длины, что и остальные. Кроме того, я понял, что исходная функция возвращала длинную строку undefined снова и снова, когда текст не был введен, поэтому есть проверка, чтобы исключить это. Поскольку теперь этот цикл всегда будет возвращать хотя бы один элемент html, я заменил цикл do на цикл while для облегчения чтения. Наконец, если вы хотите, чтобы ваше усечение всегда заканчивалось на границе слова, передайте параметр words: true при его вызове. Очевидно, что это не даст вам одинаковый уровень усечения для каждого предварительного просмотра, но улучшит читаемость. Вот и все!

person Bottled Smoke    schedule 18.03.2015
comment
Спасибо за отличную идею! Но если я обработаю кусок данных, он будет содержать теги HTML, поэтому я не смогу просто разрезать строку посередине... - person zavg; 18.03.2015
comment
Да, я понял это, поэтому я отредактировал свой ответ. Будет ли что-то подобное работать? - person Bottled Smoke; 18.03.2015
comment
IMO, самая сложная часть - найти точное регулярное выражение для вашего алгоритма. - person zavg; 18.03.2015
comment
Извините, вам не нужно регулярное выражение. Вчера это было в Сент-Пэтти. Моя голова была не в порядке, когда утро ударило, как товарный поезд. Я еще раз пересмотрел свой ответ со скрипкой, которая должна решить ваши проблемы или, по крайней мере, указать вам правильное направление (без регулярного выражения). - person Bottled Smoke; 18.03.2015
comment
Просто вау! Большое спасибо за ваши усилия и время, которое вы тратите на этот вопрос! Я бы проголосовал хотя бы 10 раз, если бы это было возможно :) - person zavg; 18.03.2015
comment
Любое время. Мы все в этом вместе :) - person Bottled Smoke; 18.03.2015
comment
Да точно! Но вы представили действительно удивительный фрагмент кода! - person zavg; 18.03.2015

Я хочу поделиться своей предварительной версией, это было довольно просто с showdown.js и prism.js подсветка синтаксиса.

Prism.js легко использует синтаксис JavaScript и CSS. Все, что вам нужно, это выбрать определенные языки и загрузить их в папку с ресурсами. Или вы можете указать его для конкретных страниц.

Это произойдет в режиме предварительного просмотра в реальном времени в форме.

В форме Rails:

<div class="col-md-12">
  <div class="form-group">
    <%= f.label :body %>
    <%= f.text_area :body, class: "form-control", rows: 10 %>
  </div>
</div>


<div class="col-md-12">
  <h1> Preview Markdown </h1>
  <div class="form-group markdownOutput"></div>
</div>

И добавьте этот скрипт прямо под страницей формы.

<script>
function mkdown(){
  var converter  = new showdown.Converter(),
      $post_body = $("#post_body");

  // This line will keep adding new rows for textarea. 
  function postBodyLengthDetector(post_body){
    var lines = post_body.val().split("\n");
    post_body.prop('rows', lines.length+5);
  }


  // Textarea rows in default '10', when focusing on this. It will expand. 
  $post_body.focus(function(){
    postBodyLengthDetector($(this));
    $('.markdownOutput').html(converter.makeHtml($post_body.val()));
  });

  // All simple magic goes here, each time when texting anything into textarea
  //it will be generated to markdown. You are able to see preview right below of textarea.
  $post_body.keyup(function() {
    postBodyLengthDetector($(this));
      var value = $( this ).val(),
          html  = converter.makeHtml(value);
          $('.markdownOutput').html(html);
  });
}
$(mkdown);
$(document).on("turbolinks:load", mkdown);
</script>
person 7urkm3n    schedule 26.04.2016