web-dev-qa-db-ja.com

Markdownをどのように解析しますか?

編集:最近、CommonMarkと呼ばれるプロジェクトについて学びました。これは、元のMarkdown仕様のあいまいさを正しく識別して処理します。 http://commonmark.org/ C#ライブラリのサポートが優れています。

構文 here を見つけることができます。

ダウンロードに続くソースは Perl で書かれていますが、これを尊重するつもりはありません。これは正規表現に満ちており、特定の文字をエスケープするために MD5 ハッシュに依存しています。それについて何かが間違っています!

Markdown のパーサーをハードコーディングしようとしています。これでの経験とは何ですか?

Markdownの実際の構文解析について何も言えない場合は、時間を節約してください。 (これは耳障りに聞こえるかもしれませんが、はい、解決策ではなく、つまりサードパーティのライブラリを探しています)。

答えを少し助けるために、正規表現はパターンを識別することを意図しています!文法全体を解析しない。人々がそうすることを検討するのは愚かです。

  • Markdownについて考えると、基本的には段落の概念に基づいています。
  • そのため、合理的なアプローチは、入力を段落に分割することです。
  • 見出し、テキスト、リスト、ブロック引用、コードなど、多くの種類の段落があります。
  • したがって、これらのパラグラフを特定し、どのような文脈で発生するかが課題です。

共有する価値があるとわかったら、ソリューションに戻ります。

122
John Leidegren

私が知っている、実際のパーサーを使用する唯一のマークダウン実装は、 Jon MacFarleane ’s peg-markdown です。 そのパーサー は、 peg と呼ばれる Parsing Expression Grammar パーサージェネレーターに基づいています。


編集: Mauricio Fernandez は最近 Simple Markup Markdownパーサー をリリースしました。これは彼の OcsiBlog Weblog Engineの一部として書いたものです。パーサーは OCaml で記述されているため、非常にシンプルで短い( パーサー の場合は268 SLOC、 HTMLエミッター の場合は43 SLOC) 、まだ blazinglyfastdiscount (手で最適化されたCで書かれた)よりも20%高速であり、_(sixhundredBlueClothRuby ))、まだパフォーマンスの最適化もされていないという事実にもかかわらず。マウリシオ自身のウェブログのための内部使用のみを目的としているため 公式のMarkdown仕様 から少し逸脱していますが、Mauricioは これらの変更のほとんどを元に戻すブランチ を作成しました。

64
Jörg W Mittag

先週、新しいパーサーベースのMarkdown Java実装、 pegdown と呼ばれる実装をリリースしました。pegdownは、最初に抽象構文ツリーを構築するためにPEGパーサーを使用します。そのため、正規表現ベースのアプローチよりも非常にクリーンで読みやすく、保守や拡張が容易ですPEG文法は、John MacFarlanes C実装「peg-markdown」に基づいています。

たぶんあなたに興味のある何か...

17
Mathias

マークダウン(およびその拡張子 Markdown extra )を解析しようとした場合、ステートマシンを使用して、一度に1文字ずつ解析し、テキストの一部を表すいくつかの内部構造をリンクしようとすると思いますそれに沿って進むと、すべてが解析されると、すべて一緒にストリング化されたオブジェクトから出力が生成されます。

基本的に、入力ファイルを読み取るときにミニDOMのようなツリーを構築します。
出力を生成するには、ツリーを走査してHTMLまたはその他のもの(PS、LaTex、RTFなど)を出力します。

複雑さを増す可能性のあるもの:

  • ルールは簡単に実装できますが、HTMLとマークダウンを混在させることができるという事実:2つのバランスのとれたタグの間にあるものはすべて無視して、そのまま出力します。

  • URLとメモは、テキストの下部に参照を含めることができます。ハイパーリンクにデータ構造を使用すると、次のようなものを簡単に記録できます。

    [my text to a link][linkkey]
    results in a structure like: 
        URLStructure: 
        |  InnerText : "my text to a link"
        |  Key       : "linkkey"
        |  URL       : <null>
    
  • ヘッダーは下線で定義できます。これにより、一般的な段落に単純なデータ構造を使用し、ファイルを読み取るときにそのプロパティを変更することができます。

    ParagraphStructure:
    |  InnerText    : the current paragraph text 
    |                 (beginning of line until end of line).
    |  HeadingLevel : <null> or 1-4 when we can assess 
    |                 that paragraph heading level, if any.
    

とにかく、いくつかの考え。

細心の注意を払うべき細部がたくさんあると確信しており、その過程で正規表現が便利になると確信しています。
結局のところ、彼らはテキストを処理するためのものでした。

6
Renaud Bompuis

おそらく構文仕様を十分に読んでそれを知り、どのように構文解析するかの感覚をつかむでしょう。

もちろん、既存のパーサーコードを読むことは、複雑さの主な原因であると思われるものを確認することと、特別な巧妙なトリックが使用されているかどうかの両方を確認するのに優れています。 MD5チェックサムの使用は少し奇妙に思えますが、なぜコードが実行されているのかを理解するのに十分なコードを研究していません。 _EscapeSpecialChars()と呼ばれるルーチン内のコメント:

これらの各文字を、対応するMD5チェックサム値に置き換えています。これはおそらくやり過ぎですが、偶然にエスケープ値と衝突するのを防ぐはずです。

1つのキャラクターを完全なMD5に置き換えることは贅沢に思えますが、おそらく理にかなっています。

もちろん、正規表現の沼から抜け出すために Flex などのツールのために、「真の」構文を作成することを検討することは賢明でしょう。

3
unwind

Perlがあなたのものでない場合は、Markdownの実装が 少なくとも他の10言語 にあります。おそらくすべてが100%の互換性を持っているわけではありませんが、かなり近い傾向があります。

2
Ken

MarkdownPapers は別のJavaパーサーが JavaCC 文法で定義されている実装です。

2
Larry Ruiz

ここ MarkdownのJavaScript実装を見つけることができます。また、これはテキストを解析するための最も高速で簡単な方法であるため、正規表現にも大きく依存しています。

ただし、MD5パーツは不要です。

解析のコーディングを直接支援することはできませんが、このリンクが何らかの形で役立つ場合があります。

0
Kosi2801

Php、Ruby、Java、c#、javascriptなど、多くの言語で利用可能なライブラリがあります。これらのいくつかを考えてみることをお勧めします。

どの言語を使用するかによって異なりますが、実装する最良の方法は、慣用的および非慣用的方法があります。

Perlと正規表現は親友であるため、正規表現はPerlで機能します。

0
garrow

他のユーザーが3人以上いるプログラミング言語を使用している場合は、解析するライブラリを見つけることができるはずです。 Googleで簡単に確認すると、CL、Haskell、Python、JavaScript、Rubyなどのライブラリが明らかになります。この車輪の再発明が必要になることはほとんどありません。

ゼロから作成する必要がある場合は、適切なパーサーを作成することをお勧めします。この手法を使用すると、MD5ハッシュで物事をエスケープする必要がなくなります。 (このようなことをしなければならない場合は、デザインを再検討する時が来たことに同意します。)

0
jrockway

MarkdownはJAWL(ちょうど別のwiki言語)です

パーサーのコードを調べることができるオープンソースのウィキがたくさんあります。ほとんどがREGEXを使用します

Screwturn wikiをご覧ください。興味深いマルチパスフォーマッタパイプラインがあり、非常に素晴らしいテクニックです。/core/Formatter.csおよび/core/FormatterPipeline.csを参照してください。

既存のプロジェクトを使用するか、参加するのが最善です。これらの種類のものは、表示されるよりも常にずっと困難です。

0
TFD