wtorek, 26 marca 2019

Jak nie tworzy膰 parsera Markdown w Node.js

Jak nie tworzy膰 parsera Markdown w Node.js

Wymy艣li艂em sobie ostatnio nowy projekt - parser markdown w node.
Za艂o偶enia by艂y proste - parser mia艂 wczytywa膰 plik tekstowy (proste) i zwraca膰 wynikowy HTML (trudne).
Tekstu nie mo偶na parsowa膰 po prostu linia po linii, bo (przyk艂adowo), w bloku blockquote mo偶e znale藕膰 si臋 dowolny inny znacznik i on te偶 musi by膰 poprawnie sparsowany.
W projekcie wyodr臋bni艂em kilka warstw:
  • Tokenizer, dziel膮cy tekst na zagnie偶d偶one podbloki tekstu o takim samym formatowaniu. Jest potrzebny, poniewa偶 Markdown mo偶e zawiera膰 zagnie偶d偶one cytaty czy bloki list. 
  • TemplateChooser, kt贸ry przyporz膮dkowuje parser do bloku, na podstawie analizy tekstu przez regexy. 
  • Kilka parser贸w, do parsowania r贸偶nych typ贸w tekstu obj臋tego znacznikami. Przyk艂adowe nazwy, to HeaderParser czy BlockquoteParser. Ka偶dy parser, wykorzystuje odpowiedni regex pobierany z utils. 
  • Format danych, w kt贸rym s艂ownie opisuje, jaki typ danych zawiera dany block i linia. 
  • Obs艂ug臋 wej艣cia.
W projekcie szybko zacz臋艂y pojawia膰 si臋 pytania, takie jak:
  • Jak ma wygl膮da膰 hierarchia dziedziczenia? 
  • Czy parsery powinny dostawa膰 tekst ze znacznikami markdown, czy nale偶y je najpierw wycina膰? Ma to du偶y wp艂yw na potencjalne zmiany w bibliotece regex贸w. 
  • Jak testowa膰, czy nie dochodzi do regresji? 
  • Jak wywo艂ywa膰 poszczeg贸lne metody z klas? Logiczne mo偶e wydawa膰 si臋 ich zagnie偶d偶anie, jednak z czasem pojawia si臋 coraz wi臋cej podpoziom贸w co nie wygl膮da dobrze. Mo偶liwe rozwi膮zania,
uwzgl臋dniaj膮ce asynchroniczno艣膰, to RxJs albo promises.
Gdy wyrywa艂em sobie w艂osy z g艂owy, poniewa偶 rezultaty prac by艂y dalekie od sukcesu, mimo po艣wi臋conych kilku dni pracy, zobaczy艂em to repozytorium...
https://codepen.io/kvendrik/pen/Gmefv
Tw贸rca zastosowa艂 zupe艂nie inne podej艣cie. Zamiast obiektowej nadmiarowo艣ci, wykorzysta艂 w pe艂ni pot臋g臋 funkcji replace() i ca艂e parsowanie, wykonuje za pomoc膮 wyra偶e艅 regularnych. Ca艂y tekst jest replacowany() przez kilkana艣cie wyra偶e艅 regularnych, w wyniku daj膮c oczekiwany wynik.
Bez kilku dziedzicz膮cych po sobie parser贸w. Bez tokenizera. Bez nadmiarowego formatu danych.

Jaki z tego wniosek?

Ca艂a otoczka, kt贸r膮 zaplanowa艂em dooko艂a rozwi膮zania, by艂a nadmiarowa. Podczas szukania rozwi膮za艅 problem贸w programistycznych, warto skupi膰 si臋 na tym, co ju偶 mo偶emy wykorzysta膰 - w moim przypadku, by艂y to wyra偶enia regularne. Dzi臋ki temu, nasz kod mo偶e robi膰 wi臋cej i by膰 znacznie prostszy.

Z drugiej strony, nadmierne uproszczenie kodu i przeparsowanie go przez kilkadziesi膮t regex贸w mo偶e bardzo utrudni膰 p贸藕niejsze zrozumienie kodu oraz p贸藕niejsze wprowadzanie w nim zmian.

Brak komentarzy:

Prze艣lij komentarz