Added support for ols, uls, and multiline codes

This commit is contained in:
j4nk 2022-12-29 11:21:53 -05:00
parent eb051f5d17
commit 3e19347ded
3 changed files with 118 additions and 19 deletions

View File

@ -3,6 +3,7 @@
;;; Commentary: ;;; Commentary:
;;; Code: ;;; Code:
(require 'cl-lib) (require 'cl-lib)
(defun getline () (defun getline ()
@ -55,39 +56,97 @@
"`\\(.*\\)`" "`\\(.*\\)`"
"<code>\\1</code>" line)))))) "<code>\\1</code>" line))))))
(defun md4tj-clean-multiline (line)
"Clean LINE of markdown syntax for ul."
(replace-regexp-in-string
"^```" ""
(replace-regexp-in-string
"^[0-9]+\\. " ""
(replace-regexp-in-string "^- " "" line))))
(defun md4tj-clean-code-for-html (line)
"Escape characters in LINE that would be misinterpreted by the browser."
(string-replace
"<" "&lt;"
(string-replace ">" "&gt;" line)))
;; Note: a "block" is the smallest unit of parsing ;; Note: a "block" is the smallest unit of parsing
;; It is normally a line of the code, but can be ;; It is normally a line of the code, but can be
;; multiple lines in the case of a block (NI) ;; multiple lines in the case of a block (NI)
(defun md4tj-process-block (codeblock) (defun md4tj-process-block (codeblock state)
"Process CODEBLOCK and return html." "Process CODEBLOCK with STATE and return html."
(cond ((string-match "^#+ " codeblock) (md4tj-process-header (md4tj-process-line codeblock))) (let ((cleanline (md4tj-clean-multiline codeblock)))
((string= "---" codeblock) "<hr>") (concat
((= (length codeblock) 0) "<br/>") ;; Beginning of multiline block
(t (md4tj-process-paragraph (md4tj-process-line codeblock))))) (cond ((eq state 'beginul) "<ul>\n<li>")
((eq state 'beginol) "<ol>\n<li>")
((eq state 'begincode) "<pre>\n<code>")
((eq state 'ul) "<li>")
((eq state 'ol) "<li>")
((eq state 'code) "")
((eq state 'endul) "</ul>\n")
((eq state 'endol) "</ol>\n")
((eq state 'endcode) "</code>\n</pre>\n")
(t ""))
;; Body
(cond ((or (eq state 'code) (eq state 'begincode)) (md4tj-clean-code-for-html cleanline))
((string-match "^#+ " cleanline) (md4tj-process-header (md4tj-process-line cleanline)))
((string= "---" cleanline) "<hr>") ;; horizontal line
((= (length cleanline) 0) "<br/>") ;; blank line
(t (md4tj-process-paragraph (md4tj-process-line cleanline))))
;; End of multiline block
(cond ((or (eq state 'ul) (eq state 'beginul)) "</li>")
((or (eq state 'ol) (eq state 'beginol)) "</li>")
((eq state 'code) "")
(t "")))))
(defun md4tj-next-block () (defun md4tj-next-state (currline prevstate)
"Retrieve the next block in the open file." "Return the state based on CURRLINE and PREVSTATE."
(let ((currline (getline))) (cond ((and (string-match "^- " currline) (not (or (eq prevstate 'beginul) (eq prevstate 'ul))) 'beginul))
(cond ((string-match "^- " currline) nil) ;; TODO ul's ((and (string-match "^- " currline) (or (eq prevstate 'beginul) (eq prevstate 'ul)) 'ul))
((string-match "^[0-9]+\\. " currline) nil) ;; TODO ol's ((and (not (string-match "^- " currline)) (or (eq prevstate 'ul) (eq prevstate 'beginul))) 'endul)
(t currline)))) ((and (string-match "^[0-9]+\\. " currline) (not (or (eq prevstate 'beginol) (eq prevstate 'ol))) 'beginol))
((and (string-match "^[0-9]+\\. " currline) (or (eq prevstate 'beginol) (eq prevstate 'ol)) 'ol))
((and (not (string-match "^[0-9]+\\. " currline)) (or (eq prevstate 'ol) (eq prevstate 'beginol))) 'endol)
((and (string-match "^```" currline) (not (or (eq prevstate 'begincode) (eq prevstate 'code))) 'begincode))
((and (not (string-match "```$" currline)) (or (eq prevstate 'begincode) (eq prevstate 'code)) 'code))
((and (string-match "```$" currline) (or (eq prevstate 'code) (eq prevstate 'begincode))) 'endcode)
(t 'normal)))
(defun md4tj-finalize (state)
"Finalizes HTML document by inserting missing end tags based on STATE."
(concat
(cond ((or (eq state 'beginul) (eq state 'ul)) "</ul>")
((or (eq state 'beginol) (eq state 'ol)) "</ol>")
((or (eq state 'begincode) (eq state 'code)) "</code>")
(t ""))
"</body>\n"
"</html>"))
(defun md4tj-parse (mdfile outfile) (defun md4tj-parse (mdfile outfile)
"Entry point to parse MDFILE and output to OUTFILE." "Entry point to parse MDFILE and output to OUTFILE."
(let ((inbuf (generate-new-buffer " in")) (let ((inbuf (generate-new-buffer " in"))
(outbuf (generate-new-buffer " out"))) (outbuf (generate-new-buffer " out"))
(state 'normal)
(line nil))
(set-buffer inbuf) (set-buffer inbuf)
(insert-file-contents mdfile) (insert-file-contents mdfile)
(goto-char (point-min)) (goto-char (point-min))
(set-buffer outbuf) (set-buffer outbuf)
(insert "<body>\n")
(while (with-current-buffer inbuf (< (point) (point-max))) (while (with-current-buffer inbuf (< (point) (point-max)))
(setq line (with-current-buffer inbuf (getline)))
(setq state (md4tj-next-state line state))
(print line)
;; Insert next line(s) into output file ;; Insert next line(s) into output file
(insert (concat (md4tj-process-block (with-current-buffer (insert (concat (md4tj-process-block line state) "\n"))
inbuf
(md4tj-next-block)))
"\n"))
;; Advance input file by a line ;; Advance input file by a line
(with-current-buffer inbuf (forward-line))) (with-current-buffer inbuf (forward-line)))
(insert (md4tj-finalize state))
;; Write outbuf to outfile
(write-region nil nil outfile nil))) (write-region nil nil outfile nil)))
(provide 'md4tj_parse) (provide 'md4tj_parse)

View File

@ -1,7 +1,32 @@
<body>
<h1>Hello <code>world</code>!</h1> <h1>Hello <code>world</code>!</h1>
<h2>Hello world!</h2> <h2>Hello world!</h2>
<h3>Hello world!</h3> <h3>Hello world!</h3>
<h4>Hello <strong><em>world</em></strong>!</h4> <h4>Hello <strong><em>world</em></strong>!</h4>
<br/> <br/>
<p><a href=https://example.com>Example website</a></p> <p><a href=https://example.com>Example website</a></p>
<p><a href=image.jpg>Example image</a></p> <p><img src=usbs.png alt=Example image></p>
<br/>
<ul>
<li><p>unordered item 1</p></li>
<li><p>unordered item 2</p></li>
<li><p>unordered item 3</p></li>
</ul>
<br/>
<ol>
<li><p>ordered item 1</p></li>
<li><p>ordered item 2</p></li>
</ol>
<br/>
<pre>
<code>
#include &lt;stdio.h&gt;
int main() {
printf("%s\n", "Hello World!");
return 0;
}
</code>
</pre>
<br/>
</body>
</html>

View File

@ -4,4 +4,19 @@
#### Hello ***world***! #### Hello ***world***!
[Example website](https://example.com) [Example website](https://example.com)
[Example image](image.jpg) ![Example image](usbs.png)
- unordered item 1
- unordered item 2
- unordered item 3
1. ordered item 1
2. ordered item 2
```
#include <stdio.h>
int main() {
printf("%s\n", "Hello World!");
return 0;
}
```