Тире и дефисы

В JavaScript-библиотеке Markdown-it особое внимание уделяется корректной интерпретации символов, отвечающих за тире и дефисы. В отличие от обычного Markdown, где один символ - часто используется как маркер списка, Markdown-it позволяет более гибко обрабатывать последовательности дефисов и определять тип тире в тексте.


Типы тире и дефисов

В текстах различают несколько символов:

  1. Дефис (-) — короткое тире, используется внутри слов (например, полуфинал, front-end).
  2. Короткое тире (, en-dash, U+2013) — применяется для обозначения диапазонов (например, 1990–2000) или отношений между элементами.
  3. Длинное тире (, em-dash, U+2014) — используется для вставок в предложение, для обозначения паузы или пояснений.

Markdown-it при обычном парсинге конвертирует только символ - в текст, оставляя его без изменений, поэтому для автоматического преобразования дефисов в тире необходимо подключать плагины или использовать дополнительные правила.


Настройка правил преобразования

Для работы с тире и дефисами можно использовать replaceText или подключить плагин, который автоматически заменяет дефис на нужное тире в определённых контекстах. Например:

const MarkdownIt = require('markdown-it');
const md = new MarkdownIt();

// Плагин для замены дефисов на тире
md.use(require('markdown-it-replace'), {
  patterns: [
    { regex: /(\d+)-(\d+)/g, replace: '$1–$2' }, // диапазоны чисел → en-dash
    { regex: /--/g, replace: '—' }              // двойной дефис → em-dash
  ]
});

const result = md.render('Годы жизни: 1990-2000. Мы получили результат -- это важно.');
console.log(result);

Пояснение:

  • (\d+)-(\d+) — захватывает диапазоны чисел и заменяет дефис на короткое тире.
  • -- — стандартный Markdown-конвеншн для длинного тире, преобразуется в em-dash.

Встроенные возможности Markdown-it

Без плагинов Markdown-it позволяет управлять символами через inline правила. Например, можно написать правило для автоматической замены двойного дефиса на длинное тире:

md.inline.ruler.before('text', 'em_dash', function(state, silent) {
  const pos = state.pos;
  if (state.src.slice(pos, pos + 2) !== '--') return false;
  if (!silent) {
    const token = state.push('text', '', 0);
    token.content = '—';
  }
  state.pos += 2;
  return true;
});

Этот подход даёт полный контроль над тем, какие последовательности символов заменяются и на что. Важные моменты:

  • state.src — исходная строка Markdown.
  • state.pos — текущая позиция парсера.
  • silent — если true, правило только проверяет, можно ли применить замену, без генерации токена.
  • state.push — создаёт новый токен с контентом (заменой символа).

Контекстная замена тире

Для корректного отображения тире важно учитывать контекст. Например:

  • Диапазоны: 10-2010–20
  • Вводные вставки: Это важно -- не забывайте.Это важно — не забывайте.
  • Сложные составные слова: front-end → оставляем дефис без изменений.

Для этого рекомендуется использовать регулярные выражения с захватом контекста:

const patterns = [
  { regex: /(\d+)-(\d+)/g, replace: '$1–$2' },        // числа
  { regex: /\s--\s/g, replace: ' — ' },              // длинное тире в тексте
  { regex: /(\w)-(\w)/g, replace: '$1-$2' }          // дефис в словах
];

Такой подход позволяет избежать некорректной замены дефиса внутри слов.


Рекомендации по интеграции

  1. Плагины упрощают обработку тире и дефисов, особенно для больших текстов.
  2. Inline правила дают максимальную гибкость, позволяют учитывать локальный контекст.
  3. Регулярные выражения — основной инструмент для замены, но требуют внимательного тестирования на разных типах текста.
  4. Сочетание нескольких подходов — оптимальный вариант для учебников, документации и сайтов с большим количеством Markdown-контента.

Практическая структура плагина

В учебных и корпоративных проектах часто создают отдельный плагин для тире:

function dashPlugin(md) {
  md.inline.ruler.before('text', 'en_dash', function(state, silent) {
    const match = state.src.slice(state.pos).match(/^(\d+)-(\d+)/);
    if (!match) return false;
    if (!silent) {
      const token = state.push('text', '', 0);
      token.content = match[1] + '–' + match[2];
    }
    state.pos += match[0].length;
    return true;
  });

  md.inline.ruler.before('text', 'em_dash', function(state, silent) {
    if (state.src.slice(state.pos, state.pos + 2) !== '--') return false;
    if (!silent) {
      const token = state.push('text', '', 0);
      token.content = '—';
    }
    state.pos += 2;
    return true;
  });
}

md.use(dashPlugin);

Такой плагин можно подключать ко всем Markdown-it-инстансам, обеспечивая единообразие тире и дефисов по проекту.


Важные нюансы

  • Markdown-it не заменяет дефис на тире автоматически без явных правил или плагинов.
  • Для корректного отображения тире в HTML лучше использовать Unicode-символы ( и ), а не – или —, чтобы сохранить совместимость с текстовыми редакторами и поисковыми системами.
  • Последовательности символов в коде (-, --) обрабатываются отдельно, чтобы не ломать форматирование списков и inline-кода.

Markdown-it предоставляет мощные инструменты для точного контроля над тире и дефисами, позволяя создавать текст с правильной типографикой без вмешательства в исходный Markdown-файл.