Markdown'u ayrıştırmaya ne dersin? [kapalı]


126

Düzenleme: Yakın zamanda, orijinal Markdown spesifikasyonundaki belirsizlikleri doğru bir şekilde tanımlayan ve bunlarla ilgilenen CommonMark adlı bir proje öğrendim. http://commonmark.org/ Harika C # kitaplık desteğine sahiptir.

Sözdizimini burada bulabilirsiniz .

İndirmeyi takip eden kaynak, benim hiçbir şeref duymadığım Perl dilinde yazılmış . Normal ifadelerle doludur ve belirli karakterlerden kaçmak için MD5 karmalarından yararlanır. Bunda bir şeyler yanlış!

Markdown için bir ayrıştırıcıyı zor kodlamak üzereyim . Bununla ilgili deneyim nedir?

Markdown'un gerçek çözümlemesi hakkında söyleyecek anlamlı bir şeyiniz yoksa, bana zaman ayırın. (Bu kulağa sert gelebilir, ancak evet, bir çözüm değil, yani üçüncü taraf bir kitaplık, içgörü arıyorum.

Cevaplara biraz yardımcı olmak için, düzenli ifadeler kalıpları tanımlamaya yöneliktir ! Bütün bir dilbilgisini AYIRMAYIN. İnsanların bunu yapmayı düşünmesi saçmadır.

  • Markdown hakkında düşünürseniz, temelde paragraf kavramına dayanır.
  • Bu nedenle, makul bir yaklaşım girdiyi paragraflara ayırmak olabilir.
  • Başlık, metin, liste, blok alıntı ve kod gibi birçok türde paragraf vardır.
  • Dolayısıyla zorluk, bu paragrafları ve hangi bağlamda ortaya çıktıklarını belirlemektir.

Paylaşılmaya değer bulduğumda bir çözümle geri döneceğim.



Ben de aynısını yaptım. Bununla birlikte, işaretlemeyi resmi bir gramermiş gibi ayrıştırmaya çalışmıyorum, çünkü açıkça değil. Farklı düzenli ifadeleri yinelemeli bir şekilde uyguladım. Ve birkaç geçişte. Bu çok iyi sonuçlandı.
John Leidegren

@JohnLeidegren, benim gibi diğer meraklı kullanıcıların markdown'u çözümleme girişiminizi görme şansı var mı?
jmlopez

@jmlopez Üzgünüz, artık o kaynağa erişimim yok, bir markdown çözümleyicisine ihtiyacınız varsa, kullanılabilecek bir NuGet paketi var. Yine de fikir yeterince basit, geçişlerde bir dizi düzenli ifade uygulayın, paragraflardaki girdiyi bölümlere ayırarak başlayın ve sonra ne tür bir paragraf olduğunu belirlemeye çalışın, vb. Son olarak, paragrafların kendi içindeki bağlantıları ve karakter stillerini ayrıştırın.
John Leidegren

2
Sen bakmak gerekir Parsedown . Metni satırlara böler. Ardından, bu çizgilerin nasıl başladığına ve birbirleriyle nasıl ilişkili olduğuna bakar.
Emanuil Rusev

Yanıtlar:


69

Gerçek bir ayrıştırıcı kullanır bildiğim tek markdown uygulama, bir Jon MacFarleane ‘ın tahta markdown . Ayrıştırıcısı , peg adı verilen Ayrıştırma İfadesi Dilbilgisi ayrıştırıcı oluşturucusuna dayanır .


DÜZENLEME: Mauricio Fernandez , OcsiBlog Weblog Engine'in bir parçası olarak yazdığı Simple Markup Markdown ayrıştırıcısını kısa süre önce yayınladı . Ayrıştırıcı yazılmış olduğu için OCaml , öyle son derece kısa, basit ve (için 268 SLOC ayrıştırıcı , 43 SLOC HTML yayıcı ), henüz blazingly hızlı (% 20 daha hızlı indirim (el-optimize edilmiş C yazılı) ve sixhundred zamanlarda daha hızlı daha BlueCloth ( Ruby)), henüz performans için optimize edilmemiş olmasına rağmen. Yalnızca Mauricio'nun kendi web günlüğü için dahili kullanım için tasarlandığından, resmi Markdown spesifikasyonundan birkaç sapma vardır , ancak Mauricio bu değişikliklerin çoğunu geri alan bir şube yaratmıştır .


1
ilginç. belki bunu bir f # projesi olarak dönüştürmeyi deneyeceğim
ShuggyCoUk

@Benjol Aynı eski hikaye: zaman yok: /
ShuggyCoUk

1
Terrence Parr ( ANTLR'nin
Chris S

17

Geçen hafta pegdown adında yeni bir ayrıştırıcı tabanlı Markdown Java uygulaması yayınladım . pegdown, önce bir soyut sözdizimi ağacı oluşturmak için bir PEG ayrıştırıcı kullanır, bu ağaç daha sonra HTML'ye yazılır. Bu nedenle oldukça temiz ve okunması, sürdürülmesi ve genişletilmesi normal ifade tabanlı bir yaklaşıma göre çok daha kolaydır. PEG grameri, John MacFarlanes C uygulaması "peg-markdown" a dayanmaktadır.

Belki seni ilgilendiren bir şey ...


1
Bu artık resmi olarak kullanımdan kaldırıldı
Fabich

7

Markdown'u (ve onun eklentisi Markdown'u ) ayrıştırmaya çalışacak olsaydım, sanırım bir durum makinesi kullanmayı ve her seferinde bir karakter ayrıştırmayı deneyecektim, o zaman ilerledikçe metin bitlerini temsil eden bazı iç yapıları birbirine bağlayarak, bir kez tümü bir araya dizilmiş nesnelerden çıktı üretilerek ayrıştırılır.

Temel olarak, girdi dosyasını okurken mini DOM benzeri bir ağaç oluşturardım.
Bir çıktı oluşturmak için, ağacı geçip HTML veya başka bir şey çıkardım (PS, LaTex, RTF, ...)

Karmaşıklığı artırabilecek şeyler:

  • Kuralın uygulanması kolay olsa da, HTML ve işaretlemeyi karıştırabileceğiniz gerçeği: iki dengeli etiket arasındaki her şeyi yok sayın ve kelimesi kelimesine çıktı alın.

  • URL'lerin ve notların referansları metnin altında olabilir. Köprüler için veri yapılarını kullanmak, aşağıdaki gibi bir şeyi kaydedebilir:

    [my text to a link][linkkey]
    results in a structure like: 
        URLStructure: 
        |  InnerText : "my text to a link"
        |  Key       : "linkkey"
        |  URL       : <null>
    
  • Başlıklar, bizi genel bir paragraf için basit bir veri yapısı kullanmaya ve dosyayı okurken özelliklerini değiştirmeye zorlayabilecek bir alt çizgi ile tanımlanabilir:

    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.
    

Her neyse, sadece bazı düşünceler.

Eminim ilgilenilmesi gereken birçok küçük ayrıntı vardır ve bu işlem sırasında Regex'lerin kullanışlı olabileceğinden oldukça eminim.
Sonuçta, metni işlemeleri gerekiyordu.


3

Muhtemelen sözdizimi özelliğini bilmek için yeterince zaman okudum ve nasıl ayrıştırılacağına dair bir fikir edinirim.

Mevcut ayrıştırıcı kodunu okumak, hem karmaşıklığın ana kaynağının ne olduğunu görmek hem de herhangi bir özel zekice hile kullanılıp kullanılmadığını görmek için elbette harikadır. MD5 sağlama toplamının kullanımı biraz tuhaf görünüyor, ancak kodu neden yapıldığını anlayacak kadar çalışmadım. Durum adı verilen bir rutinde bir yorum _EscapeSpecialChars():

Bu tür karakterlerin her birini karşılık gelen MD5 sağlama toplamı değeriyle değiştiriyoruz; bu muhtemelen aşırıdır, ancak bizim kaçış değerleriyle kazara çarpışmamızı önlemelidir.

Tek bir karakteri tam bir MD5 ile değiştirmek abartılı görünebilir, ancak belki de gerçekten mantıklı.

Elbette, Flex gibi bir aracın normal ifade bataklığından çıkması için "gerçek" bir sözdizimi oluşturmayı düşünmek akıllıca olacaktır .


Bu MD5 olayı beni hala rahatsız ediyor, ayrıca aşırı dize manipülasyonu, kendi kendinize yazabileceğiniz gerçek düzgün ayrıştırıcılardan daha yavaş olmalı.
John Leidegren

2
Flex, gerçekten ayrıştırıcının yalnızca yarısıdır; Girdiyi belirteç haline getirdikten sonra, belirteçlerin ne anlama geldiğini belirlemeniz gerekir. Ayrıştırıcı üreteci bunun içindir. Onlardan çok var. ("Ayrıştırıcı birleştirici", "yinelemeli-iniş" ve "LALR (1)", google'ın anahtar kelimeleridir.)
jrockway

1
@jrockway: bu tabii ki doğru, sanırım omuz silktim ve "ama Flex'i okursa, Bison'u otomatik olarak bulacak" diye düşündüm. :) Teşekkürler.
04

2

Perl size göre değilse, en az 10 başka dilde Markdown uygulamaları vardır . Muhtemelen hepsinin% 100 uyumluluğu yoktur, ancak oldukça yakın olma eğilimindedirler.



1

Üçten fazla kullanıcısı olan bir programlama dili kullanıyorsanız, onu sizin için ayrıştıracak bir kitaplık bulabilmelisiniz. Hızlı bir Google-ing, CL, Haskell, Python, JavaScript, Ruby vb. İçin kitaplıkları ortaya çıkarır. Bu tekerleği yeniden icat etmeniz gerekmeyecek.

Gerçekten sıfırdan yazmanız gerekiyorsa, uygun bir ayrıştırıcı yazmanızı tavsiye ederim. Bu teknikle, MD5 hash'leri ile şeylerden kaçmanız gerekmeyecek. (Böyle bir şey yapmanız gerekiyorsa, tasarımınızı yeniden gözden geçirme zamanının geldiğine katılıyorum.)


Ben meydan okumaya hazırım. Kütüphanelere baktım ama berbatlar. Çirkin ve aptal. Ayrıştırıcıyı F # ile yazmayı düşünüyorum çünkü bir F # projesine ihtiyacım var ama muhtemelen bunu C # ile yapacağım.
John Leidegren

Umarım F #, Parsec gibi bir kitaplığa sahiptir; eğer öyleyse, bu eğlenceli bir proje olacak;)
jrockway

0

Php, ruby, java, c #, javascript dahil olmak üzere bir dizi dilde mevcut olan kütüphaneler vardır. Fikir almak için bunlardan bazılarına bakmanızı öneririm.

Hangi dili kullanmak istediğinize bağlıdır, onu uygulamanın en iyi yolu için, bunu yapmanın deyimsel ve deyimsel olmayan yolları olacaktır.

Normal ifadeler perl'de çalışır, çünkü perl ve regex en iyi arkadaştır.


1
Regex ve perl en iyi arkadaşlar çünkü biri öyle dedi. Bu gerçek, tarihsel soydan daha fazla gerçek olamaz, bu şekilde kullanılmış. Perl gibi bir şeye ihtiyacım yok.
John Leidegren

7
O zaman kullanma .. Ayrıca ironiyi de öğren.
garrow

0

Markdown bir JAWL'dir (sadece başka bir wiki dili)

Ayrıştırıcının kodunu inceleyebileceğiniz pek çok açık kaynak wiki var. Çoğu kullanım REGEX

Screwturn wiki'ye göz atın, ilginç bir çok geçişli formatlayıcı ardışık düzenine sahip, çok güzel bir teknik - bkz. /Core/Formatter.cs ve /core/FormatterPipeline.cs

En iyisi mevcut bir projeyi kullanmak / katılmaktır, bu tür şeyler her zaman göründüğünden çok daha zordur


0

Burada Markdown'un JavaScript uygulamasını bulabilirsiniz. Ayrıca, metni ayrıştırmanın en hızlı ve en kolay yolu olduğundan, büyük ölçüde normal ifadelere dayanır.

Ancak MD5 bölümünü ayırıyor.

Çözümlemenin kodlanmasına doğrudan yardımcı olamam, ancak bu bağlantı size bir şekilde yardımcı olabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.