;;; 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 "")) (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 "\\*\\(.*\\)\\*" "\\1" ;; Then strong (replace-regexp-in-string "\\*\\*\\(.*\\)\\*\\*" "\\1" ;; First code (replace-regexp-in-string "`\\(.*\\)`" "\\1" 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) "
") (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