Added support for ols, uls, and multiline codes
This commit is contained in:
parent
eb051f5d17
commit
3e19347ded
|
@ -3,6 +3,7 @@
|
|||
;;; Commentary:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
|
||||
(defun getline ()
|
||||
|
@ -55,39 +56,97 @@
|
|||
"`\\(.*\\)`"
|
||||
"<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
|
||||
"<" "<"
|
||||
(string-replace ">" ">" line)))
|
||||
|
||||
|
||||
;; Note: a "block" is the smallest unit of parsing
|
||||
;; It is normally a line of the code, but can be
|
||||
;; multiple lines in the case of a block (NI)
|
||||
(defun md4tj-process-block (codeblock)
|
||||
"Process CODEBLOCK and return html."
|
||||
(cond ((string-match "^#+ " codeblock) (md4tj-process-header (md4tj-process-line codeblock)))
|
||||
((string= "---" codeblock) "<hr>")
|
||||
((= (length codeblock) 0) "<br/>")
|
||||
(t (md4tj-process-paragraph (md4tj-process-line codeblock)))))
|
||||
(defun md4tj-process-block (codeblock state)
|
||||
"Process CODEBLOCK with STATE and return html."
|
||||
(let ((cleanline (md4tj-clean-multiline codeblock)))
|
||||
(concat
|
||||
;; Beginning of multiline block
|
||||
(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 ()
|
||||
"Retrieve the next block in the open file."
|
||||
(let ((currline (getline)))
|
||||
(cond ((string-match "^- " currline) nil) ;; TODO ul's
|
||||
((string-match "^[0-9]+\\. " currline) nil) ;; TODO ol's
|
||||
(t currline))))
|
||||
(defun md4tj-next-state (currline prevstate)
|
||||
"Return the state based on CURRLINE and PREVSTATE."
|
||||
(cond ((and (string-match "^- " currline) (not (or (eq prevstate 'beginul) (eq prevstate 'ul))) 'beginul))
|
||||
((and (string-match "^- " currline) (or (eq prevstate 'beginul) (eq prevstate 'ul)) 'ul))
|
||||
((and (not (string-match "^- " currline)) (or (eq prevstate 'ul) (eq prevstate 'beginul))) 'endul)
|
||||
((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)
|
||||
"Entry point to parse MDFILE and output to OUTFILE."
|
||||
(let ((inbuf (generate-new-buffer " in"))
|
||||
(outbuf (generate-new-buffer " out")))
|
||||
(outbuf (generate-new-buffer " out"))
|
||||
(state 'normal)
|
||||
(line nil))
|
||||
(set-buffer inbuf)
|
||||
(insert-file-contents mdfile)
|
||||
(goto-char (point-min))
|
||||
(set-buffer outbuf)
|
||||
(insert "<body>\n")
|
||||
(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 (concat (md4tj-process-block (with-current-buffer
|
||||
inbuf
|
||||
(md4tj-next-block)))
|
||||
"\n"))
|
||||
(insert (concat (md4tj-process-block line state) "\n"))
|
||||
;; Advance input file by a line
|
||||
(with-current-buffer inbuf (forward-line)))
|
||||
(insert (md4tj-finalize state))
|
||||
;; Write outbuf to outfile
|
||||
(write-region nil nil outfile nil)))
|
||||
|
||||
(provide 'md4tj_parse)
|
||||
|
|
|
@ -1,7 +1,32 @@
|
|||
<body>
|
||||
<h1>Hello <code>world</code>!</h1>
|
||||
<h2>Hello world!</h2>
|
||||
<h3>Hello world!</h3>
|
||||
<h4>Hello <strong><em>world</em></strong>!</h4>
|
||||
<br/>
|
||||
<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 <stdio.h>
|
||||
int main() {
|
||||
printf("%s\n", "Hello World!");
|
||||
return 0;
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
<br/>
|
||||
</body>
|
||||
</html>
|
|
@ -4,4 +4,19 @@
|
|||
#### Hello ***world***!
|
||||
|
||||
[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;
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue