git.fiddlerwoaroof.com
Browse code

Add new formatting framework

fiddlerwoaroof authored on 30/01/2017 20:53:12
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,78 @@
1
+(defpackage :alimenta.format
2
+  (:use :cl :alexandria :serapeum :fw.lu))
3
+(in-package :alimenta.format)
4
+
5
+(defclass document-formatter ()
6
+  ())
7
+
8
+(defclass indent-formatter (document-formatter)
9
+  ((%level :initarg :level :accessor level :initform 0)))
10
+
11
+(defclass html-formatter (document-formatter)
12
+  ((%level :initarg :level :accessor level :initform 0)))
13
+
14
+(defgeneric format-document (formatter stream document)
15
+  (:documentation "Format a document with the given formatter to the given stream"))
16
+
17
+(defgeneric format-title (formatter title)
18
+  (:documentation "Format a title according to FORMATTER"))
19
+
20
+(defgeneric format-link (formatter link)
21
+  (:documentation "Format a link according to FORMATTER"))
22
+
23
+(defgeneric format-paragraph (formatter paragraph)
24
+  (:documentation "Format a paragraph according to FORMATTER"))
25
+
26
+(defmethod format-title ((formatter indent-formatter) (title string))
27
+  (format nil "+ Title: ~a" title))
28
+
29
+(defmethod format-title ((formatter html-formatter) (title string))
30
+  (format nil "<h~d>~a~2:*</h~d>" (1+ (level formatter)) title))
31
+
32
+(defmethod format-link ((formatter indent-formatter) (link string))
33
+  (format nil "  Link: ~a" link))
34
+
35
+(defmethod format-link ((formatter html-formatter) (link string))
36
+  (format nil "<a href=\"~a\">~:*~a</a>" link))
37
+
38
+(defmethod format-paragraph ((formatter indent-formatter) (paragraph list))
39
+  (format nil "~{  ~a~}" paragraph))
40
+
41
+(defmethod format-paragraph ((formatter html-formatter) (paragraph list))
42
+  (format nil "~%~{<p>~a</p>~}" paragraph))
43
+
44
+
45
+(defmethod format-document (formatter stream (document alimenta::feed-entity))
46
+  (format stream "~&~v,4@t~a~%~v,4@t~a~%"
47
+	  (level formatter) (format-title formatter (alimenta:title document))
48
+	  (level formatter) (format-link formatter (alimenta:link document))))
49
+
50
+(defmethod format-document (formatter stream (document alimenta:item))
51
+  (call-next-method)
52
+  (let ((paragraphs (lquery:$ (initialize (alimenta:content document))
53
+			      (children)
54
+			      (text))))
55
+    (format stream "~&~v,4@t~a~2&"
56
+	    (level formatter) (format-paragraph formatter (map 'list #'identity paragraphs)))))
57
+
58
+(defmethod format-document ((formatter indent-formatter) stream (document alimenta:feed))
59
+  (call-next-method)
60
+  (incf (level formatter))
61
+  (for:for ((item over document))
62
+    (format-document formatter stream item)))
63
+
64
+(defmethod format-document ((formatter html-formatter) stream (document alimenta:feed))
65
+  (let ((ostream (or stream (make-string-output-stream))))
66
+    (unwind-protect
67
+	 (progn (format ostream "~&<html><head></head><body><main>~%")
68
+		(call-next-method formatter ostream document)
69
+		(incf (level formatter))
70
+		(for:for ((item over document))
71
+		  (format ostream "~&<article>~%")
72
+		  (format-document formatter ostream item)
73
+		  (format ostream "~&</article>~%"))
74
+		(format ostream "~&</main></body></html>~%")
75
+		(finish-output ostream)
76
+		(get-output-stream-string ostream))
77
+      (unless stream
78
+	(close ostream)))))