95 lines
3.1 KiB
EmacsLisp
95 lines
3.1 KiB
EmacsLisp
;;; md4tj_parse --- Summary
|
|
|
|
;;; Commentary:
|
|
|
|
;;; Code:
|
|
(require 'cl-lib)
|
|
|
|
(defun getline ()
|
|
"Get current line from loaded buffer."
|
|
(buffer-substring-no-properties (line-beginning-position) (line-end-position)))
|
|
|
|
(defun md4tj-begin-tag (tag &optional attrs)
|
|
"Return beginning html tag for TAG with optional ATTRS."
|
|
(concat "<" tag
|
|
(mapconcat 'identity (cl-map 'listp (lambda (l) (concat " " (nth 0 l) "=" (nth 1 l))) attrs) "")
|
|
">"))
|
|
|
|
(defun md4tj-end-tag (tag)
|
|
"Return end html tag for TAG."
|
|
(concat "</" tag ">"))
|
|
|
|
(defun md4tj-process-header (line)
|
|
"Process LINE known to be header, return HTML."
|
|
(let ((level (length (nth 0 (split-string line)))))
|
|
(if (or (< level 0) (> level 6))
|
|
(error (concat "Error parsing: " line "\n"))
|
|
(concat (md4tj-begin-tag (concat "h" (number-to-string level)))
|
|
(mapconcat 'identity (cdr (split-string line)) " ")
|
|
(md4tj-end-tag (concat "h" (number-to-string level)))))))
|
|
|
|
(defun md4tj-process-paragraph (line)
|
|
"Process LINE that is paragraph, return HTML."
|
|
(concat (md4tj-begin-tag "p") line (md4tj-end-tag "p")))
|
|
|
|
(defun md4tj-process-line (line)
|
|
"Process all inline elements of the LINE, return HTML."
|
|
;; Finally links
|
|
(replace-regexp-in-string
|
|
"\\[\\(.*\\)\\](\\(.*\\))"
|
|
(concat (md4tj-begin-tag "a" (list '("href" "\\2"))) "\\1" (md4tj-end-tag "a"))
|
|
;; Then images
|
|
(replace-regexp-in-string
|
|
"!\\[\\(.*\\)\\](\\(.*\\))"
|
|
(md4tj-begin-tag "img" (list '("src" "\\2") '("alt" "\\1")))
|
|
;; Then emphasis
|
|
(replace-regexp-in-string
|
|
"\\*\\(.*\\)\\*"
|
|
"<em>\\1</em>"
|
|
;; Then strong
|
|
(replace-regexp-in-string
|
|
"\\*\\*\\(.*\\)\\*\\*"
|
|
"<strong>\\1</strong>"
|
|
;; First code
|
|
(replace-regexp-in-string
|
|
"`\\(.*\\)`"
|
|
"<code>\\1</code>" 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-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-parse (mdfile outfile)
|
|
"Entry point to parse MDFILE and output to OUTFILE."
|
|
(let ((inbuf (generate-new-buffer " in"))
|
|
(outbuf (generate-new-buffer " out")))
|
|
(set-buffer inbuf)
|
|
(insert-file-contents mdfile)
|
|
(goto-char (point-min))
|
|
(set-buffer outbuf)
|
|
(while (with-current-buffer inbuf (< (point) (point-max)))
|
|
;; Insert next line(s) into output file
|
|
(insert (concat (md4tj-process-block (with-current-buffer
|
|
inbuf
|
|
(md4tj-next-block)))
|
|
"\n"))
|
|
;; Advance input file by a line
|
|
(with-current-buffer inbuf (forward-line)))
|
|
(write-region nil nil outfile nil)))
|
|
|
|
(provide 'md4tj_parse)
|
|
;;; md4tj_parse.el ends here
|