Каково идеальное регулярное выражение для форматирования вики (.Net)? - PullRequest
2 голосов
/ 04 декабря 2008

H ребята, у меня есть этот алгоритм форматирования вики, который я использую в Stacked для создания HTML из "синтаксиса вики", и я не совсем уверен, хорош ли текущий используемый мной алгоритм достаточно, оптимально или содержит ошибки, так как я на самом деле не "Regex Guru". Вот что я сейчас использую;

<code>// Body is wiki content...
string tmp = Body.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
// Sanitizing carriage returns...
tmp = tmp.Replace("\\r\\n", "\\n");

// Replacing dummy links...
tmp = Regex.Replace(
" " + tmp,
"(?<spaceChar>\\s+)(?<linkType>http://|https://)(?<link>\\S+)",
"${spaceChar}<a href=\"${linkType}${link}\"" + nofollow + ">${link}</a>",
RegexOptions.Compiled).Trim();

// Replacing wiki links
tmp = Regex.Replace(tmp,
"(?<begin>\\[{1})(?<linkType>http://|https://)(?<link>\\S+)\\s+(?<content>[^\\]]+)(?<end>[\\]]{1})",
"<a href=\"${linkType}${link}\"" + nofollow + ">${content}</a>",
RegexOptions.Compiled);

// Replacing bolds
tmp = Regex.Replace(tmp,
"(?<begin>\\*{1})(?<content>.+?)(?<end>\\*{1})",
"<strong>${content}</strong>",
RegexOptions.Compiled);

// Replacing italics
tmp = Regex.Replace(tmp,
"(?<begin>_{1})(?<content>.+?)(?<end>_{1})",
"<em>${content}</em>",
RegexOptions.Compiled);

// Replacing lists
tmp = Regex.Replace(tmp,
"(?<begin>\\*{1}[ ]{1})(?<content>.+)(?<end>[^*])",
"<li>${content}</li>",
RegexOptions.Compiled);
tmp = Regex.Replace(tmp,
"(?<content>\\<li\\>{1}.+\\<\\/li\\>)",
"<ul>${content}</ul>",
RegexOptions.Compiled);

// Quoting
tmp = Regex.Replace(tmp,
"(?<content>^&gt;.+$)",
"<blockquote>${content}</blockquote>",
RegexOptions.Compiled | RegexOptions.Multiline).Replace("</blockquote>\n<blockquote>", "\n");

// Paragraphs
tmp = Regex.Replace(tmp,
"(?<content>)\\n{2}",
"${content}</p><p>",
RegexOptions.Compiled);

// Breaks
tmp = Regex.Replace(tmp,
"(?<content>)\\n{1}",
"${content}<br />",
RegexOptions.Compiled);

// Code
tmp = Regex.Replace(tmp,
"(?<begin>\\[code\\])(?<content>[^$]+)(?<end>\\[/code\\])",
"<pre class=\"code\">${content}
», RegexOptions.Compiled); // Теперь, надеюсь, tmp будет содержать идеальный HTML

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

Вот полный "синтаксис вики";

Синтаксис здесь:

Link; [http://x.com text]

*bold* (asterisk on both sides)

_italic_ (underscores on both sides)

* Listitem 1
* Listitem 2
* Listitem 3
(the above is asterixes but so.com also creates lists from it)

2 x Carriage Return is opening a new paragraph

1 x Carriage Return is break (br)

[code]
if( YouDoThis )
  YouCanWriteCode();
[/code]


> quote (less then operator)

Если есть какие-то "гуру регулярных выражений", которые хотели бы пересмотреть эту логику регулярных выражений, я был бы очень признателен:)

1 Ответ

4 голосов
/ 04 декабря 2008

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

Парсер, который имеет некоторое представление о контексте и вложенности, здесь намного лучше.

Можете ли вы опубликовать полный образец разрешенного синтаксиса, чтобы люди могли дать вам представление о том, как его проанализировать?


РЕДАКТИРОВАТЬ: Вы можете изучить возможность использования (потенциально измененного) Markdown парсера для этого. Для .NET доступен вариант с открытым исходным кодом: Markdown.NET , по крайней мере, стоит взглянуть на исходный код. Может быть, изменить его в соответствии с вашими потребностями не так уж сложно.

...