Экранирование Discord подмножество уценки

Я пытаюсь избежать подмножества уценки, которое поддерживает Discord (*, _, `, ~). У уже сбежавших персонажей не должно быть добавлено дополнительной обратной косой черты. Вот что у меня есть:

function escapeMarkdown(text) {
 return text.replace(/([^\\]|^|\*|_|`|~)(\*|_|`|~)/g, '$1\\$2');
}

console.log(escapeMarkdown('*test* _string_ ~please~ `ignore` *_`~kthx \*  \\~'));

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

1 ответ

Я бы посоветовал удалить все уже экранированные символы, а затем снова экранировать все:

function escapeMarkdown(text) {
  var unescaped = text.replace(/\\(\*|_|`|~|\\)/g, '$1'); // unescape any "backslashed" character
  var escaped = unescaped.replace(/(\*|_|`|~|\\)/g, '\\$1'); // escape *, _, `, ~, \
  return escaped;
}

var str = '*test* _string_ ~please~ `ignore` *_`~kthx \*  \\~ C:\\path\\to\\file';
console.log("Original:");
console.log(str);
console.log("Escaped:");
console.log(escapeMarkdown(str));

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

var markdownEscape = function(text) {
   return text.replace(/((\_|\*|\~|\`|\|){2})/g, '\\$1');
};

console.log(markdownEscape('||some spoiler text||'));

Он добавит обратную косую черту перед любым символом в регулярном выражении, если их два.

Я знаю, что это в ruby, а не в js, но это может быть тривиально переведено в JS, оно экранирует все известные специальные символы разногласий (+ предотвращает предпросмотр со ссылками)

  def escape(str)
    # \ -> \\
    str = str.gsub("\\") { "\\\\" }
    # - -> \_
    str = str.gsub('_') { "\\_" }
    # * -> \*
    str = str.gsub('*') { "\\*" }
    # ~ -> \~
    str = str.gsub('~') { "\\~" }
    # ` -> \`
    str = str.gsub('`') { '\\`' }
    # | -> \|
    str = str.gsub('|') { '\\|' }
    # urls without previews
    str = str.gsub(/https?:\/\/[\S]+/) { |url| "<#{url}>" }

    str
  end

(Я публикую это здесь, так как я уверен, что это может помочь будущим читателям, и, похоже, это единственное место, где говорят об этой проблеме)

И вот строка, полная Discord, форматирующая вещи как бонус:

Italics *italics* or _italics_
Underline italics __*underline italics*__
Bold **bold**
Underline bold __**underline bold**__
Bold Italic ***bold italics***
underline bold italics __***underline bold italics***__
Underline __underline__
Strikethrough  ~~Strikethrough~~
Link https://google.com https://mathiasbynens.be/demo/url-regex
Code: `inline`

```
block
```

```ruby
block with language
```

Spoiler: ||spoiler||
Другие вопросы по тегам