;;; md4tj --- Summary
;;; Commentary:
;;; Code:
(require 'cl-lib)
(require 'subr-x)
;; Change this line to wherever dash.el is on the building system
;; Can't use (require) because load-path is set in .emacs
(load-file "~/.emacs.d/elpa/dash-20230415.2324/dash.el")
;; Basic utilities for subsequent stuff
(defun md4tj-util-getline ()
  "Get current line from loaded buffer."
  (buffer-substring-no-properties (line-beginning-position) (line-end-position)))
(defun md4tj-util-clean-multiline (line)
  "Clean LINE of markdown syntax for ul's, ol's and code's."
  (replace-regexp-in-string
   "^```" ""
   (replace-regexp-in-string
	"^[0-9]+\\. " ""
	(replace-regexp-in-string "^- " "" line))))
(defun md4tj-util-escape-chars (line)
  "Escape characters in LINE that would be misinterpreted by the browser."
  (string-replace
   "<" "<"
   (string-replace ">" ">" line)))
(defun md4tj-util-zip (ls)
  "Turn list of lists LS into list of tuples."
  (cl-labels ((zip-help (ll) (if (not (car ll)) nil (cons (cl-map 'listp #'car ll) (zip-help (cl-map 'listp 'cdr ll))))))
	(zip-help ls)))
;; End basic utilities
;; Normal md4tj stuff
(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 strikethrough
  (replace-regexp-in-string
   "~~\\(.*\\)~~"
   "\\1"
   ;; Then highlight
   (replace-regexp-in-string
	"==\\(.*\\)=="
	"\\1"
	;; Then 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 videos
	  (replace-regexp-in-string
	   "!!\\[\\([^\\[]*\\)](\\([^\\[(]*\\))"
	   (concat (md4tj-begin-tag "video" (list '("src" "\\2") '("type" "video/webm") '("controls" "true"))) "\\1" (md4tj-end-tag "video"))
	   ;; Then emphasis
	   (replace-regexp-in-string
		"\\*\\(.*\\)\\*"
		"\\1"
		;; Then strong
		(replace-regexp-in-string
		 "\\*\\*\\(.*\\)\\*\\*"
		 "\\1"
		 ;; First code
		 (replace-regexp-in-string
		  "`\\(.*\\)`"
		  "\\1" line)))))))))
				  
(defun md4tj-convert-line-to-html (line state inbuf outfile)
  "Process LINE with STATE and return html, INBUF provided with OUTFILE."
  (let ((cleanline (md4tj-util-clean-multiline line)))
	;; If this is a signal to include another file
	(cond ((string-match "^@@INCLUDE" line) (md4tj-parse-to-string (nth 1 (split-string line))))
		  ((string-match "^@@LASTUPDATED" line) (concat
												 (md4tj-begin-tag "p" (list (list "id" "lastupdated")))
												 "Last updated: " (format-time-string "%a %d %b %Y %H:%M UTC" nil t)
												 (md4tj-end-tag "p")))
		  ((string-match "^@@DIV" line) (md4tj-begin-tag "div" (list (list "class" (nth 1 (split-string line))))))
		  ((string-match "^@@ENDDIV" line) (md4tj-end-tag "div"))
		  ((string-match "^@@BLOGINSERT" line) (with-current-buffer inbuf (md4tj-blog-html)))
		  ((string-match "^@@RSSINSERT" line) (md4tj-rss-link-string (concat (with-current-buffer inbuf (save-excursion (md4tj-blog-base-url))) "feed.xml")))
		  ((and (string-match "^$$.*$$" line) (eq (nth 1 state) 'normal)) ;; LaTeX formula
		   (shell-command (concat "./pnglatex"
								  " -d 300"
								  " -f "
								  "\""
								  (string-replace "$$" "" line)
								  "\""
								  " -o "
								  "./teximg/"
								  (md5 (string-replace "$$" "" line)) ".png"))
		   (md4tj-begin-tag "img" (list (list "class" "teximg") ;; give teximgs their own class
										(list "src" (concat "./teximg/" (md5 (string-replace "$$" "" line)) ".png"))
										(list "alt" (string-replace "$$" "" line)))))
		  ;; If this is some other signal, ignore
		  ((string-match "^@@" line) "")
		  ;; Otherwise, process as normal
		  (t
		   (concat
			;; Beginning multiline block/ending prev multiline block
			(mapconcat #'md4tj-state-to-html state "\n")
			
			;; Body
			(cond ((or (eq (nth 1 state) 'code) (eq (nth 1 state) 'begincode)) (md4tj-util-escape-chars cleanline))
				  ((string-match "^#+ " cleanline) (md4tj-process-header (md4tj-process-line cleanline)))
				  ((string= "---" cleanline) "
\n")
		((eq state 'ul) "- ")
		((eq state 'ol) "
- ")
		((eq state 'code) "")
		((eq state 'endul) "