ERK'2022, Portorož, 351-354 351 Razširitev oznaˇ cevalnega jezika Markdown z aritmetiˇ cnimi operacijami, matematiˇ cnimi in logiˇ cnimi funkcijami v tabelah Aleks Mariniˇ c, Tomaž Kosar Fakulteta za elektrotehniko, raˇ cunalništvo in informatiko, Univerza v Mariboru, Koroška cesta 46, 2000 Maribor E-pošta: aleks.marinic@student.um.si, tomaz.kosar@um.si Extending the Markdown Markup Language with Arithmetic Operations, Mathematical and Logical Functions in Tables Markdown is a simple markup language used to format text with plain-text editors that use additional tools to display formatted text or even generate HTML. It is pop- ular among programmers because the syntax is easy to learn. However, simple and minimalistic Markdown no- tation can be problematic for those with more elaborate needs. In this article, we present how to extend the exist- ing Markdown language. We developed an extension for mathematical and logical functions in combination with general arithmetic operators in tables. The syntax is similar to that of table functions in spreadsheet pro- grammes but with some modifications adapted for Mark- down. Other developers with similar additional needs can learn how to use Markdown language and adjust it using our extension method. 1 Uvod Markdown spada med oznaˇ cevalne jezike in se upora- blja za prevajanje surovega besedila v HTML ali drug podoben jezik [3]. Ta majhen domensko specifiˇ cen je- zik [4, 5, 6] se uporablja v forumih za oblikovanje objav in za oblikovanje besedilnih datotek (npr. README.md - vodnik, ki daje uporabniku kratek opis projekta [7] v GitHub, GitLab in podobnih repozitorijih). Vse pogo- steje pa ga sreˇ camo tudi v drugaˇ cnih okolišˇ cinah, kot je izdelava statiˇ cnih spletnih strani (npr. Jekyll [1]) in v iz- delavi predstavitev (npr. Slidev [2]). S široko paleto ukazov pokriva veˇ cino zahtev nava- dnih uporabnikov in z raznimi dodatki tudi naprednih v specifiˇ cnih okolišˇ cinah. Študenti se radi naslanjajo na Markdownova programja za izdelavo zapiskov, saj z njimi hitro vizualno uredijo besedilo, videz pa celotnem dokumentu konsistenten. Predavatelji pa zaradi delje- nih predstavitev v obliki strežniške storitve vse pogosteje uporabljajo orodje Slidev. Enostavna in minimalistiˇ cna notacija Markdown, pa lahko za tiste z veˇ c potrebami predstavlja težavo. Upo- raba aritmetiˇ cnih operatorjev v kombinaciji z matematiˇ c- nimi in logiˇ cnimi funkcijami je velik plus, ko zapisujemo doloˇ cene podatke v tabelah. Funkcije v tabelah so hitre in natanˇ cne rešitve, saj je prepisovanje ter roˇ cno raˇ cuna- nje podatkov dolgotrajno in lahko se pojavijo površne na- pake. V tem ˇ clanku predstavljamo, kako se lotiti razširitve jezika Markdown. Razvili smo razširitev za matematiˇ cne in logiˇ cne funkcije v kombinaciji s splošnimi aritmetiˇ c- nimi operatorji v tabelah, kakršnih smo uporabniki nava- jeni iz programov za urejanje preglednic (npr. Microsoft Excel). Sintaksa je podobna tem, vendar z nekaterimi modifikacijami prilagojenimi za Markdown. ˇ Clanek ima sedem poglavij. V drugem poglavju pred- stavimo motivacijo naše razširitve. Sledi tretje poglavje, kjer je predstavljen prevajalnik jezika Markdown. V ˇ ce- trtem poglavju je predstavitev implementacije razširitve. Peto poglavje predstavi implementirane funkcije, ki jih lahko uporabljamo v tabelah Markdown. Šesto poglavje prikazuje uporabo naše razširitve na realnih problemih. Zadnje poglavje povzame vsebino ˇ clanka. 2 Motivacija za razširitev jezika Mark- down Ob pisanju razliˇ cnih dokumentov velikokrat uporabljamo tabele za preglednejši prikaz doloˇ cenih podatkov. Veˇ c- krat nam je iz vseh teh podatkov najpomembnejša infor- macija, ki pa jo treba izraˇ cunati, na primer: na raˇ cunu kupca nas najbolj zanima vsota zneska, na anketi se po- datki predstavijo v obliki odstotnega deleža itd. Oznaˇ cevalni jezik Markdown privzeto ne podpira no- benih aritmetiˇ cnih operacij, matematiˇ cnih ali logiˇ cnih funkcij v tabelah in vse raˇ cunanje ob vsaki spremembi je treba opraviti roˇ cno in vnesti rezultat. Ob tem se pojavlja velika verjetnost raˇ cunske ali tipkarske napake ˇ cloveka. Te potrebne manjkajoˇ ce funkcionalnosti smo dodali v obliki razširitve prevajalnika s paleto ukazov, oblikovanih po konceptu: ==[arit. operacije in mat./log. funkcije]== Oznaˇ cba == oznaˇ cuje meje aritmetiˇ cnih operacij, ma- tematiˇ cnih in logiˇ cnih funkcij v tabeli. Te so v obliki ope- racij, kot jih poznamo iz popularnih programov za ureja- nje preglednic, na primer: ==if(sum(A2-A5) > 100, B3, "premalo")== ==avg(B3-B16)== 352 Primer uporabe funkcije samodejne vsote je na sliki 1, kjer smo s pomoˇ cjo uporabe matematiˇ cne funk- cije hitro izraˇ cunali samodejno vsoto. Rezultat kode je viden na sliki 2. Slika 1: Markdown zapis primera o zbiranju sredstev Slika 2: Izhodni izpis primera o zbiranju sredstev 3 Prevajalnik jezika Markdown Za implementacijo rešitve je bil potreben prevajalnik je- zika Markdown. Ker obstojeˇ cih ukazov oznaˇ cevalnega jezika ne bomo spreminjali, smo se odloˇ cili vzeti že ob- stojeˇ c prevajalnik in mu dodali razširitev. Potrebovali smo odprtokodni projekt, ki ga lahko prosto spreminjamo in distribuiramo. Med široko paleto raznih prevajalni- kov Markdown smo se odloˇ cili za Marked [8], saj ima možnost prevajanja prek ukazne vrstice ali klasiˇ cne Ja- vaScript knjižnice. Prav tako je eden izmed bolj prilju- bljenih prevajalnikov za Markdown, ki ga uporabniki radi nadgrajujejo, saj ima veliko vejitev. Je tudi živ projekt, saj ga redno nadgrajuje zdaj že okoli 150 razvijalcev. Projekt je razvit v zalednem izvajalskem okolju Node.js, ki ga je zaˇ cel razvijati Christopher Jeffrey [9] leta 2011 in ga najdemo pod licenco MIT. Koda projekta se prevaja, surova pa se hrani v mapi ./src. Ob prevajanju se zgradi v zgošˇ ceno datoteko JavaScript 1 . Poslediˇ cno je datoteka manjše velikosti in se ob zahtevi hitreje prenese na raˇ cunalnik odjemalca. 3.1 Struktura kode prevajalnika Celotna koda projekta Marked se deli na razrede, metode in funkcije v razliˇ cnih datotekah – vse znotraj mape ./src. Zaˇ cetna toˇ cka je datoteka marked.js. Ta vsebuje funk- cijo marked(...), ki jo kliˇ cemo v dokumentu HTML zno- traj znaˇ cke SCRIPT in ji kot parameter podamo besedilo Markdown za prevajanje. Besedilo se nato pregleda s pomoˇ cjo regularnih izra- zov (ki so v datoteki rules.js) in razliˇ cnimi metodami zno- traj razreda Lexer (v datoteki Lexer.js). Posamezne me- tode se uporabljajo za razrezanje besedila glede na ukaze in klic ustreznih metod znotraj razreda Tokenizer (v dato- teki Tokenizer.js) za izdelavo tako imenovanih žetonov. 1 Vsebuje manjšo dolžino kode, saj so iz nje izbrisani nepotrebni pra- zni znaki in zamenjana so imena nekaterih spremenljivk. Žetoni so objekti, ki hranijo posamezne lastnosti uka- zov (med drugim tip, surov in obdelan ukaz). Te žetone sprejmejo ustrezne metode znotraj razreda Parser (v da- toteki Parser.js) in glede na njihovo vrsto pokliˇ ce ustre- zno metodo v razredu Renderer (iz datoteke Renderer.js). Posamezna metoda vstavi parametre žetona v vnaprej de- finirano definirano HTML in jo vrne v obliki niza znakov (angl. string) nazaj. Pri tem se uporabljajo še druge metode znotraj razre- dov: • TextRenderer, ki je v datoteki TextRenderer.js. Nje- gove metode vraˇ cajo vsebino znotraj ukazov in • Slugger, ki je v datoteki Slugger.js. Omogoˇ ca gene- racijo enoliˇ cno doloˇ cenih identifikatorjev (vredno- sti ID atributov znotraj naslovnih znaˇ ck). Med brezrazredne funkcije štejemo še getDefaults in setDefaults iz datoteke defaults.js (ki skrbita za branje in nastavljanje vnaprej definiranih vrednosti) ter pomožne funkcije iz helpers.js, kjer so definirane funkcije za ostale namene. 3.2 Vstopna toˇ cka za razširitev prevajalnika Nove implementirane matematiˇ cne in logiˇ cne funkcije kot tudi osnovne aritmetiˇ cne operacije so namenjene iz- vajanju samo v tabelah. Poslediˇ cno se morajo potencialni ukazi iskati samo znotraj celic tabele in ne potrebujemo globalnega iskanja podatkov. Uporabili smo rekurzivno funkcijo CellCalcula- tor(...). Kot parameter prejme tabelo in posamezno ce- lico (ki obravnava) in (neobvezno oziroma vnaprej de- finirano) iteracijo izvajanja funkcije. Iteracija izvajanja se uporablja za prepreˇ cevanje klica rekurzije v neskonˇ c- nost ob uporabi nepravilne reference (na celico) ob klicu posameznih funkcij oziroma ob pojavljanju semantiˇ cnih napak. Ta funkcija se prviˇ c kliˇ ce v datoteki Tokenizer.js med oblikovanjem prejetega niza znakov v objekt. Tako se funkcija izraˇ cuna pred gradnjo tabele v niz znakov za iz- pis. Uporabljeni koncept loˇ cevanje razredov in funkcij po kriterijih v razliˇ cne datoteke je tukaj smiselno uporabljen zaradi globalnih iskanj posameznih ukazov (na primer: naslovi, odebeljeno besedilo, povezave, ...). Mi upora- bljamo ukaze za funkcije le znotraj celic tabel in po- slediˇ cno je bolj primerno lokalno iskanje ukazov. Ker imamo drugaˇ cne (unikatne) kriterije iskanja, je primerno, da loˇ cimo tudi kodo v svojo datoteko. S tem drugim raz- vijalcem nakažemo drugaˇ cnost in je koda kot celota tudi bolj pregledna. Loˇ cena datoteka za kodo je smiselno poi- menovana TableFunction.js in ima glavno funkcijo – ta je CellCalculator(. . . ), pomožne funkcije in globalne kon- stante. 4 Implementacija razširitve Programska implementacija se deli na dve bistveni funk- ciji za obdelavo, nekaj pomožnih in treh konstantnih objektov. Pomožne funkcije se uporabljajo za: 353 • pretvorbo klica reference celice (na primer: BA34) v objekt s številko stolpca in vrstice referencirane celice, • napredno izlušˇ cenje vgnezdene funkcije, defini- rane z veˇ ckratnim gnezdenjem oklepajev, • prepisovanje obstojeˇ ce funkcije parseFloat zaradi odprave napake zaokroževanja ob shranjevanju de- cimalnih vrednosti v 64-bitna števila s plavajoˇ co vejico ipd. Posamezne aritmetiˇ cne operacije in tudi matematiˇ cne in logiˇ cne funkcije so predstavljene s tremi konstantnimi objekti. Te tvorijo regularni izrazi za detekcijo funkcije in izlušˇ cevanje njenih parametrov ter funkcija za obdelavo. Dodana je možnost za onemogoˇ cenje razširitve. To se definira v klicu metode setOptions(...), kjer nastavimo vrednost tableFunctions na false: marked.setOptions({tableFunctions: false}); 4.1 Funkcija CellCalculator (...) Predstavlja glavno funkcijo, ki izlušˇ ci celotni matema- tiˇ cni in/ali logiˇ cni izraz iz vsebine celice ter ga posreduje naprej funkciji solveFunction(...), ki vrne odgovor na me- sto, kjer je bil prej iskani izraz. Iskanje funkcije poteka s pomoˇ cjo regularnega izraza med robnimi oznakami==. Funkcija s pomoˇ cjo rekurzivnega števca iteracij ob se- mantiˇ cni napaki v funkciji prepreˇ cuje klice v neskonˇ c- nost. Privzeto število rekurzivnih klicev funkcije brez iz- pisa napak je 25 in ko se to število preseže, dobimo na- pako. ˇ Ce hoˇ cemo uporabljati veˇ c ali manj rekurzivnih kli- cev, lahko to dosežemo s klicem metode setOptions(...), kjer nastavimo vrednost tableFunctionRecursionNumber na želeno število: marked.setOptions({ tableFunctionRecursionNumber: 35 }); 4.2 Funkcija solveFunction (...) Je rekurzivna funkcija, ki prejme izlušˇ ceno funkcijo v obliki niza in celotno tabelo ter (neobvezno – vnaprej de- finirano) iteracijo. Posamezni ukazi se v matematiˇ cnem in/ali logiˇ cnem izrazu prepoznajo s pomoˇ cjo regularnih izrazov in obde- lajo po prednosti matematiˇ cnih pravil. ˇ Ce je v matematiˇ c- nem in/ali logiˇ cnem izrazu referenca na celico (na primer: A1), se ta prav tako obravnava kot loˇ cen izraz in se ob- dela samostojno v novem klicu iste rekurzivne funkcije. Enako se zgodi v primeru oklepajev, saj je tudi tam veˇ cja prednost raˇ cunanja. Ko se izraz izraˇ cuna in imamo v od- govoru samo eno število (ali opomin napake), se vrne v oˇ cetovsko funkcijo. Zadnjo oˇ cetovsko funkcijo predsta- vlja glavna funkcija, poklicana v datoteki Tokenizer.js. Pri uporabi matematiˇ cnih ali logiˇ cnih funkcij lahko pride do napak, te se delijo na semantiˇ cne in sintaktiˇ cne. Semantiˇ cne napake nastanejo ob uporabi referenc na ce- lice brez števil ali uporabi matematiˇ cno nepravilnih ra- ˇ cunskih operacij (na primer: deljenje z 0, kvadratni koren negativnih števil). Ob tem se izpiše odgovor NaN. Sin- taktiˇ cne napake pa nastanejo ob napaˇ cni uporabi mate- matiˇ cnih operatorjev ali neobstojeˇ cih/nepravilno podanih matematiˇ cnih/logiˇ cnih funkcij. Ob tem se izpiše odgovor [ERROR]. 5 Dodane funkcije za delo s tabelami Dodani so bili osnovni aritmetiˇ cni operatorji (seštevanje, odštevanje, množenje, deljenje in potenciranje) in najbolj priljubljene osnovne matematiˇ cne in logiˇ cne funkcije. 5.1 Matematiˇ cne funkcije Matematiˇ cne funkcije se izvajajo nad podatki v obsegu. Le-ta je doloˇ cen z znakom – (pomišljaj). Vse matema- tiˇ cne funkcije pokliˇ cemo z krajšavo njihovega imena in zatem dodamo oklepaje, v katerih je definiran obseg. V nadaljevanju podajamo nekaj dodanih matematiˇ c- nih funkcij v naši razširitvi jezika Markdown: • Samodejna vsota se uporablja za seštevanje celic v definiranem obsegu tabele. Primer klica funkcije za raˇ cunanje samodejne vsote: sum(A1-C5). • Minimalna vrednost se uporablja za iskanje naj- manjše vrednosti v definiranem obsegu tabele. Pri- mer klica funkcije za iskanje minimalne vrednosti: min(A1-C5). • Maksimalna vrednost se uporablja za iskanje naj- veˇ cje vrednosti v definiranem obsegu tabele. Pri- mer klica funkcije za iskanje maksimalne vredno- sti: max(A1-C5). • Povpreˇ cna vrednost (ali aritmetiˇ cna sredina) se uporablja za raˇ cunanje povpreˇ cne vrednosti v de- finiranem obsegu tabele. Primer klica funkcije za raˇ cunanje povpreˇ cne vrednosti: avg(A1-C5). Kot rezultat vse matematiˇ cne funkcije vrnejo število ali obvestilo o napaki. 5.2 Funkcija za logiˇ cno preverjanje Pogojni stavek se uporablja za pogojni izpis ali raˇ cunanje v doloˇ ceni celici. Funkcijo pokliˇ cemo z imenom, zatem dodamo oklepaje, v katerih so 3 deli, loˇ ceni z dvema ve- jicama. Prvo je pogoj, nato prvi stavek in drugi stavek. Prvi stavek se uporabi, ko je pogoj resniˇ cen, in drugi, ko pogoj ni resniˇ cen. Primer klica take funkcije je: if(A1>0, "Poz. št.", "Neg. št.") Kot odgovor vrne zapis Poz. št. (kar oznaˇ cuje pozi- tivno število veˇ cje od 0) ali Neg. št. (kar oznaˇ cuje 0 ali negativno število ). 6 Uporaba razširitev oznaˇ cevalnega jezika Markdown Podajmo nekaj primerov uporabe naše razširitve jezika Markdown. 354 6.1 Primer raˇ cunanja niˇ cel funkcije Veliko ljudi uporablja razne programske rešitve za iz- delovanje zapiskov. Ko pišemo matematiˇ cne zapiske, lahko uporabljamo podatke v tabelah za hitro izraˇ cunava- nje vrednosti. Na sliki 3 je primer zapiska, kjer hoˇ cemo izraˇ cunati niˇ cli polinoma, podanega (1) prek enaˇ cb (2) in (3). Temu primeren izhod pa je na sliki 4. f(x) = 4x 2 +4x− 4 (1) x 1, 2 = − b± √ D 2a (2) D =b 2 − 4ac (3) Slika 3: Zapis primera Markdown o iskanju niˇ cel polinoma Slika 4: Izhodni izpis primera o iskanju niˇ cel polinoma 6.2 Primer raˇ cunanja deležev Kadar pišemo poroˇ cila anket ali eksperimentov, moramo te tudi primerno predstaviti. Na sliki 5 je primer ankete o starosti obiskovalcev neke knjižnice. Matematiˇ cne funk- cije lahko uporabimo neposredno za raˇ cunanje deležev. Ob spremembah podatkov se deleži samodejno preraˇ cu- najo in imamo takoj ustvarjeno novo poroˇ cilo. Primer kode raˇ cunanja deležev iz podatkov v tabeli je prikazan na sliki 5, njen izhodni rezultat pa na sliki 6. Slika 5: Zapis Markdown primera o raˇ cunanju deležev 7 Zakljuˇ cek Markdown ni samo oznaˇ cevalni jezik, paˇ c pa je celovit projekt, ki raste in se širi v nova okolja. Med uporabniki je priljubljen, saj je sintaksa lahka, kratka in preprosta za Slika 6: Izhodni zapis primera o raˇ cunanju deležev uˇ cenje. Uporabniki (ki dobro poznajo sintakso) tudi ve- liko hitreje napišejo dokument, saj jim pri vizualnem ure- janju dokumenta ni treba delati premikov rok s tipkovnice na miško. Hkrati je tudi vizualni izgled dokumenta boljši, saj je vnaprej doloˇ cen in v vseh dokumentih konsistenten. Naša razširitev je kot projekt javna na GitHub repo- zitoriju [10] in je na voljo drugim za uporabo ali nadgra- dnjo. S tem je zasnovan koncept za uporabo aritmetiˇ cnih operacij s kombinacijo matematiˇ cnih in logiˇ cnih funkcij v tabelah za priljubljeni oznaˇ cevalni jezik Markdown. S tem ˇ clankom smo želeli pokazati, kako lahko drugi razvi- jalci s potrebami po razširitvi uporabijo jezik Markdown in ga prilagodijo svojim potrebam. Literatura [1] Jekyll, https://jekyllrb.com [2] Slidev, https://sli.dev [3] Xie, Y ., Dervieux, C. Riederer, E. R markdown cookbook. (Chapman, 2020). [4] Mernik, M., Heering, J. Sloane, A. When and How to Deve- lop Domain-Specific Languages. ACM Computing Surveys. 37, 316–344 (2005). [5] Kosar, T., Bohra, S. Mernik, M. Domain–Specific Langu- ages: A Systematic Mapping Study. Information And Soft- ware Technology. 71, 77–91 (2016). [6] Kosar, T., Gaberc, S., Carver, J. Mernik, M. Program com- prehension of domain-specific and general-purpose langu- ages: replication of a family of experiments using integra- ted development environments. Empirical Software Engi- neering. 23, 2734–2763 (2018). [7] L. Richards, J. M. Morse: README FIRST for a User’s Guide to Qualitative Methods, 2013. [8] Marked, https://github.com/markedjs/marked [9] C. Jeffrey, https://github.com/chjj/ [10] Marked with table functions, https://github.com/Linux- Alex/marked-with-table-functions