Last active
April 11, 2025 09:17
-
-
Save sogaiu/09975ae019fce55b2c971c466cc87f1f to your computer and use it in GitHub Desktop.
tweaked mendoza.janet from initial commit of mendoza
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# parse docstring's flavor of markdown | |
# based on initial commit of mendoza by bakpakin | |
(defn- combine-strings | |
"Flatten consecutive strings in an indexed structure by concatenating | |
them. The resulting document graph should be much cleaner. Also, empty | |
strings will be removed entirely." | |
[els] | |
(def buf @"") | |
(def accum @[]) | |
(defn bflush [] | |
(unless (empty? buf) | |
(array/push accum (string buf)) | |
(buffer/clear buf))) | |
(loop [x :in els] | |
(if (bytes? x) | |
(buffer/push-string buf x) | |
(do (bflush) (array/push accum x)))) | |
(bflush) | |
(tuple/slice accum)) | |
(defn- capture-tokens | |
"Wrapper to make combine-strings variadic and useful as a subtitution | |
function in the peg grammar." | |
[& args] | |
(combine-strings args)) | |
(defn- line-el | |
"Create a peg pattern for parsing some markup | |
on a line. Captures the HTML text to output." | |
[delim tag] | |
(defn replace | |
[& args] | |
{:tag tag | |
:content (combine-strings args)}) | |
~(* ,delim | |
(/ (any (if-not ,delim :token)) ,replace) | |
,delim)) | |
(defn- capture-code | |
"Peg capture function for single line of code" | |
[code] | |
{:tag "code" | |
"class" "medoza-code" | |
:content [code]}) | |
(defn- capture-li | |
"Capture a list inside the peg and create a Document Node." | |
[& contents] | |
{:tag "li" | |
:content (combine-strings contents)}) | |
(defn- capture-ol | |
"Capture a list inside the peg and create a Document Node." | |
[& contents] | |
{:tag "ol" | |
:content (combine-strings contents)}) | |
(defn- capture-ul | |
"Capture a list inside the peg and create a Document Node." | |
[& contents] | |
{:tag "ul" | |
:content (combine-strings contents)}) | |
(defn- capture-paragraph | |
"Capture a paragraph node in the peg." | |
[& contents] | |
{:tag "p" | |
:content (combine-strings contents)}) | |
(def- md-grammar | |
"Grammar for markdown -> document AST parser." | |
~{:next (any (+ (set "\t \n\r") -1)) | |
:opt-ws (any (set "\t ")) | |
:nl-char (+ (* (? "\r") "\n") -1) | |
:nl ':nl-char | |
:escape (* "\\" '1) | |
:strong ,(line-el "**" "strong") | |
:em ,(line-el "*" "em") | |
:code (* "`" (/ '(any (if-not "`" 1)) ,capture-code) "`") | |
:token (* ':opt-ws | |
(+ :strong :em :code :escape '(if-not :nl-char 1))) | |
:lines (some (* (some :token) :opt-ws :nl)) | |
:li (* (/ (some :token) ,capture-li) :nl) | |
:ulli (* :opt-ws (set "-*") :li) | |
:olli (* :opt-ws (some (range "09")) "." :li) | |
:ul (* (/ (some :ulli) ,capture-ul) :nl) | |
:ol (* (/ (some :olli) ,capture-ol) :nl) | |
:paragraph (/ (* :lines :nl-char) ,capture-paragraph) | |
:main (any (* :next | |
(+ :ul :ol :paragraph -1 (error ""))))}) | |
(def- md-peg | |
"A peg that converts markdown to html." | |
(peg/compile md-grammar)) | |
(defn md-parse | |
"Parse docstring markdown and return a dom." | |
[source] | |
(def matches (peg/match md-peg source)) | |
(unless matches (error "bad docstring markdown")) | |
# | |
{:tag "div" | |
:content matches}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment