-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoptimize.lisp
125 lines (108 loc) · 4.06 KB
/
optimize.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
(in-package #:hecss)
(defclass css-optimizer ()
())
(defmacro with-output-to-accumulator ((accumulator-var) &body body)
`(let ((,accumulator-var (make-string-output-stream)))
(unwind-protect (progn
,@body)
(if ,accumulator-var
(close ,accumulator-var)))))
(defun optimize-css (optimizer rules)
(check-type rules list)
(let (collected)
(with-output-to-accumulator (accumulator)
(labels ((finished-batch-strings ()
(let ((bof (get-output-stream-string accumulator)))
(unless (zerop (length bof))
(push bof collected))))
(collect (thing)
(let ((*print-case* :downcase))
(if (typep thing '(or string symbol character number))
(princ thing accumulator)
(prog1 nil
(finished-batch-strings)
(push thing collected))))))
(let ((*collect* #'collect))
(css-optimize optimizer rules)
(finished-batch-strings)
(nreverse collected))))))
(defgeneric css-optimize (optimizer element))
(defmethod css-optimize ((optimizer css-optimizer) (anything t))
(collect anything))
(defmethod css-optimize ((optimizer css-optimizer) (rules list))
(dolist (rule rules)
(css-optimize optimizer rule)
(collect #\Newline)))
#+nil(defmethod css-optimize ((optimizer css-optimizer) (color color-reference))
(let* ((color (find-palette-mapping (css-env-palette *css-env*) (color-reference-name color)))
(rgb (etypecase color
(rgb color)
(hsv (hsv-to-rgb color))))
(hex (format nil "#~A" (rgb-hex rgb))))
(collect hex)))
(defmethod css-optimize ((optimizer css-optimizer) (rule css-rule))
(let ((selectors (rule-selectors rule))
(declarations (rule-declarations rule)))
(unless selectors
(error "A css rule must have at least one selector!"))
(css-optimize optimizer (first selectors))
(dolist (selector (cdr selectors))
(collect ", ")
(css-optimize optimizer selector))
(collect " {")
(dolist (dec declarations)
(collect (format nil "~% "))
(css-optimize optimizer dec))
(collect (format nil "~%}"))))
(defmethod css-optimize ((optimizer css-optimizer) (sel css-simple-selector))
(let ((type (simple-selector-type sel))
(specifiers (simple-selector-specifiers sel)))
(if (or (string/= type "*")
(not specifiers))
(collect type))
(dolist (specifier specifiers)
(css-optimize optimizer specifier))))
(defmethod css-optimize ((optimizer css-optimizer) (sel css-id-selector))
(collect "#")
(css-optimize optimizer (id-selector-id sel)))
(defmethod css-optimize ((optimizer css-optimizer) (sel css-class-selector))
(collect ".")
(css-optimize optimizer (class-selector-name sel)))
(defmethod css-optimize ((optimizer css-optimizer) (sel css-pclass-selector))
(collect ":")
(css-optimize optimizer (pclass-selector-name sel)))
(defmethod css-optimize ((optimizer css-optimizer) (sel css-attribute-selector))
(with-readers ((attribute attribute-selector-attribute)
(type-operator attribute-selector-type-operator)
(type attribute-selector-type)
(operand attribute-selector-operand)) sel
(collect "[")
(collect attribute)
(collect type-operator)
(unless (eq type :set)
(collect "\"")
(collect operand)
(collect "\""))
(collect "]")))
(defmethod css-optimize ((optimizer css-optimizer) (sel css-compound-selector))
(css-optimize optimizer (left-selector sel))
(collect (ecase (compound-selector-relation sel)
(:descendant " ")
(:child " > ")
(:adjacent " + ")))
(css-optimize optimizer (right-selector sel)))
(defmethod css-optimize ((optimizer css-optimizer) (dec css-declaration))
(collect (declaration-property dec))
(collect ": ")
(css-optimize optimizer (declaration-value dec))
(collect ";"))
(defmethod css-optimize ((optimizer css-optimizer) (css-list css-list))
(let ((elements (css-list-elements css-list)))
(when elements
(let ((separator (ecase (css-list-type css-list)
(:space " ")
(:comma ", "))))
(css-optimize optimizer (car elements))
(dolist (element (cdr elements))
(collect separator)
(css-optimize optimizer element))))))