be more rational about sorting index
[cmcms:cmcms.git] / src / cmcms.sh
1 #!/bin/bash
2
3 # cmcms == ClaudiusMaximus Content Management System
4 # Copyright (C) 2008,2009,2010  Claude Heiland-Allen <claudiusmaximus@goto10.org>
5 #
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU Affero General Public License for more details.
15 #
16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19 if [[ ! ( "x${1}" == "xversion" || "x${1}" == "xinit" || "x${1}" == "xadd" || ( "x${1}" == "xgen" && "x${2}" != "x" && -f "${2}" ) ) ]]
20 then
21   cat <<-USAGE
22 Usage:
23     $(basename "${0}") help         -- display this usage information
24     $(basename "${0}") version      -- display version information
25     $(basename "${0}") init         -- initialize a new site
26     $(basename "${0}") add          -- add a new page
27     $(basename "${0}") gen [config] -- generate output site from "config"
28 USAGE
29   exit $( [[ "x${1}" == "xhelp" ]] )
30 fi
31
32 case "${1}" in
33   "version")
34     cat <<-VERSION
35 cmcms 0.3
36 Copyright (C) 2008,2009,2010  Claude Heiland-Allen <claudiusmaximus@goto10.org>
37 This is free software; see the source for copying conditions.  There is NO
38 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
39 VERSION
40     exit 0
41     ;;
42   "init")
43     echo "$(basename "${0}"): init: not yet implemented, sorry"
44     exit 1
45     ;;
46   "add")
47     if [[ ! -d "pages/" ]]
48     then
49       echo "$(basename "${0}"): add: directory not found: \`pages/'"
50       exit 1
51     fi
52     DATEFULL="$(date --iso=s)"
53     DATESHORT="${DATEFULL:0:10}"
54     read -e -p "date       : " -i "${DATEFULL}" PAGEDATE
55     read -e -p "title      : " PAGETITLE
56     read -e -p "url        : " -i "${DATESHORT}_$(echo "${PAGETITLE}" | sed "s|[^-_a-zA-Z0-9]|_|g" | tr "[:upper:]" "[:lower:]" | tr -s "_")" PAGEURL
57     read -e -p "summary    : " PAGESUMMARY
58     read -e -p "tag(s)     : " PAGETAGS
59     read -e -p "gallery(s) : " PAGEGALLERIES
60     PAGEFILE="pages/${PAGEURL}.xml"
61     if [[ -f "${PAGEFILE}" ]]
62     then
63       echo "WARNING : file already exists: \`${PAGEFILE}'"
64       PAGEFILE="pages/cmcms.$$.xml"
65       if [[ -f "${PAGEFILE}" ]]
66       then
67         echo "ERROR   : file already exists: \`${PAGEFILE}'"
68         exit 1
69       fi
70       echo "WARNING : writing alternative: \`${PAGEFILE}'"
71     fi
72     (
73       cat <<-TEMPLATE
74 <page>
75 <date>${PAGEDATE}</date>
76 <file>${PAGEURL}</file>
77 <title>${PAGETITLE}</title>
78 <summary><div xmlns="http://www.w3.org/1999/xhtml">
79 <p>${PAGESUMMARY}</p>
80 </div></summary>
81 <content><div xmlns="http://www.w3.org/1999/xhtml">
82 <!-- delete this line and replace with your content -->
83 TEMPLATE
84       for gallery in ${PAGEGALLERIES}
85       do
86         echo "<div class=\"gallery\">${gallery}</div>"
87       done
88       echo "</div></content>"
89       for gallery in ${PAGEGALLERIES}
90       do
91         echo "<gallery>${gallery}</gallery>"
92       done
93       for tag in ${PAGETAGS}
94       do
95         echo "<tag>${tag}</tag>"
96       done
97       echo "</page>"
98     ) > "${PAGEFILE}"
99     echo "output saved to \`${PAGEFILE}', now edit it to add content"
100     exit 0
101     ;;
102 esac
103
104 # -------------------
105 echo "Configuring..."
106 # -------------------
107
108 source "${2}"
109
110 # make paths absolute
111 IDIR="$(dirname "${2}")"
112 if [ "x/" = "x${OUT:1:0}" ]
113 then
114   ODIR="${OUT}"
115 else
116   ODIR="$(dirname "${2}")/${OUT}"
117 fi
118 if [ "x/" = "x${TMP:1:0}" ]
119 then
120   TDIR="${TMP}"
121 else
122   TDIR="$(dirname "${2}")/${TMP}"
123 fi
124
125 # ------------------
126 echo "Setting up..."
127 # ------------------
128
129 mkdir -p "${ODIR}" "${TDIR}"
130 PAGES="${TDIR}/pages.xml"
131 (
132   echo "<pages>" &&
133   cat $( ls -1 --quoting-style=escape "${IDIR}/pages/"*.xml | sort -r ) &&
134   echo "</pages>"
135 ) > "${PAGES}"
136 INDEX="${TDIR}/index.txt"
137 (
138   cat "${PAGES}" |
139   xsltproc "$(dirname "${0}")/extract.xsl" - &&
140   echo "0000-00-00 END  END "
141 ) | sort -nr > "${INDEX}"
142 (
143   echo "<pages>" &&
144   cat "${INDEX}" |
145   head -n -1 |
146   while read date file tags
147   do
148     cat "${IDIR}/pages/${file}.xml"
149   done &&
150   echo "</pages>"
151 ) > "${PAGES}"
152
153
154 # ----------------------------
155 echo "Generating tag cloud..."
156 # ----------------------------
157
158 (
159   echo "<div class=\"tagcloud\"><span class=\"title\">Tags</span><ul>" &&
160   cat "${PAGES}" |
161   xsltproc "$(dirname "${0}")/tags.xsl" - |
162   sort |
163   uniq -c |
164   while read count tag
165   do
166     class="$(echo "x=${count};sqrt(x);" | bc)"
167     link="<a href=\"${tag}.html\" title=\"${tag}\">${tag}</a>"
168     echo "<li class=\"popularity${class}\">${link}</li>"
169   done &&
170   echo "</ul></div>"
171 ) > "${TDIR}/cloud.xml"
172
173 # -------------------------------
174 echo "Generating recent posts..."
175 # -------------------------------
176
177 (
178   echo "<div class=\"recent\"><span class=\"title\">Recent</span><ul>" &&
179   cat "${INDEX}" | head -n-1 | head -n 12 |
180   while read date file tags
181   do
182     cat "${IDIR}/pages/${file}.xml" |
183     xsltproc "$(dirname "${0}")/recent.xsl" -
184   done
185   echo "</ul></div>"
186 ) > "${TDIR}/recent.xml"
187
188 # ------------------------------------
189 echo "Generating header and footer..."
190 # ------------------------------------
191
192 (
193   echo "<div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"header\">" &&
194   cat "${IDIR}/theme/header.xml" &&
195   cat "${TDIR}/cloud.xml" &&
196   cat "${TDIR}/recent.xml" &&
197   echo "</div>"
198 ) > "${TDIR}/header.xml"
199
200 (
201   echo "<div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"footer\">" &&
202   cat "${IDIR}/theme/footer.xml" &&
203   echo "</div>"
204 ) > "${TDIR}/footer.xml"
205
206 # ----------------------------
207 echo "Generating galleries..."
208 # ----------------------------
209
210 cat "${PAGES}" |
211 xsltproc "$(dirname "${0}")/galleries.xsl" - |
212 sort |
213 uniq |
214 while read gallery
215 do
216   (
217     echo "<div xmlns=\"http://www.w3.org/1999/xhtml\" class=\"gallery\">"
218     for i in "${IDIR}/gallery/${gallery}/"*
219     do
220       image="$(basename "${i}")"
221       thumb="${image/%.jpg/_thumb.jpg}"
222       thumb="${thumb/%.png/_thumb.jpg}"
223       alt="${thumb/%_thumb.jpg/}"
224       img="<img src=\"g/${gallery}/${thumb}\" alt=\"${alt}\" />"
225       link="<a href=\"g/${gallery}/${image}\" title=\"${alt}\">${img}</a>"
226       echo "<div>${link}</div>"
227     done
228     echo "<div class=\"separator\" />"
229     echo "</div>"
230   ) > "${TDIR}/gallery_${gallery}.xml"
231 done
232
233 # --------------------------------
234 echo "Generating content pages..."
235 # --------------------------------
236
237 DATENEXT=""
238 DATETHIS=""
239 DATEPREV=""
240 PAGENEXT=""
241 PAGETHIS=""
242 PAGEPREV=""
243 TAGSTHIS=""
244 TAGSPREV=""
245 NAVIGATION="${TDIR}/navigation.xml"
246 cat "${INDEX}" |
247 while read date file tags
248 do
249   DATENEXT="${DATETHIS}"
250   DATETHIS="${DATEPREV}"
251   DATEPREV="${date}"
252   PAGENEXT="${PAGETHIS}"
253   PAGETHIS="${PAGEPREV}"
254   PAGEPREV="${file}"
255   TAGSTHIS="${TAGSPREV}"
256   TAGSPREV="${tags}"
257   if [[ "x${DATEPREV}" == "x0000-00-00" || "x${PAGEPREV}" == "xEND" ]]
258   then
259     DATEPREV=""
260     PAGEPREV=""
261     TAGSPREV=""
262   fi
263   if [[ "x${PAGETHIS}" != "x" ]]
264   then
265     (
266       cat <<-NAVIGATION
267 <navigation>
268 <by-date>
269 <later>${PAGENEXT}</later>
270 <date>${DATETHIS}</date>
271 <earlier>${PAGEPREV}</earlier>
272 </by-date>
273 NAVIGATION
274       for tag in ${TAGSTHIS}
275       do
276         cat "${INDEX}" |
277         grep "^[^ ]* [^ ]* .* ${tag} .*$" |
278         grep -A 1 -B 1 "${PAGETHIS}" |
279         (
280           read dummy1 TAGFILE dummy2
281           if [[ "x${TAGFILE}" == "x${PAGETHIS}" ]]
282           then
283             TAGNEXT=""
284             TAGTHIS="${TAGFILE}"
285             read dummy1 TAGFILE dummy2
286             TAGPREV="${TAGFILE}"
287           else
288             TAGNEXT="${TAGFILE}"
289             read dummy1 TAGFILE dummy2
290             TAGTHIS="${TAGFILE}"
291             read dummy1 TAGFILE dummy2
292             TAGPREV="${TAGFILE}"
293           fi
294           cat <<-NAVIGATION
295 <by-tag>
296 <later>${TAGNEXT}</later>
297 <tag>${tag}</tag>
298 <earlier>${TAGPREV}</earlier>
299 </by-tag>
300 NAVIGATION
301         )
302       done
303       echo "</navigation>"
304     ) > "${NAVIGATION}"
305     (
306       cat "${PAGES}" |
307       xsltproc \
308         --path "${TDIR}" \
309         --stringparam SITENAME "${NAME}" \
310         --stringparam HEADER "header.xml" \
311         --stringparam FOOTER "footer.xml" \
312         --stringparam NAVIGATION "navigation.xml" \
313         --stringparam PAGE "${PAGETHIS}" \
314         "$(dirname "${0}")/page.xsl" -
315     ) >"${ODIR}/${PAGETHIS}.html"
316   fi
317 done
318
319 # ----------------------------
320 echo "Generating tag pages..."
321 # ----------------------------
322
323 cat "${PAGES}" |
324 xsltproc "$(dirname "${0}")/tags.xsl" - |
325 sort |
326 uniq |
327 while read tag ;
328 do
329   cat "${PAGES}" |
330   xsltproc \
331     --path "${TDIR}" \
332     --stringparam SITENAME "${NAME}" \
333     --stringparam HEADER "header.xml" \
334     --stringparam FOOTER "footer.xml" \
335     --stringparam tag "${tag}" \
336     "$(dirname "${0}")/tag.xsl" - >"${ODIR}/${tag}.html"
337 done
338
339 # -----------------------------
340 echo "Generating index page..."
341 # -----------------------------
342
343 cat "${PAGES}" |
344 xsltproc \
345   --path "${TDIR}" \
346   --stringparam SITENAME "${NAME}" \
347   --stringparam HEADER "header.xml" \
348   --stringparam FOOTER "footer.xml" \
349   "$(dirname "${0}")/index.xsl" - >"${ODIR}/index.html"
350
351 # --------------------------------
352 echo "Generating tag RSS feeds..."
353 # --------------------------------
354
355 cat "${PAGES}" |
356 xsltproc "$(dirname "${0}")/tags.xsl" - |
357 sort |
358 uniq |
359 while read tag ;
360 do
361   cat "${PAGES}" |
362   xsltproc \
363     --path "${TDIR}" \
364     --stringparam TITLE "${tag} :: ${NAME}" \
365     --stringparam URL "${URL}" \
366     --stringparam DESCRIPTION "${NAME} ${tag} feed" \
367     --stringparam TAG "${tag}" \
368     "$(dirname "${0}")/rss20tag.xsl" - >"${ODIR}/${tag}.rss"
369 done
370
371 # --------------------------------
372 echo "Generating main RSS feed..."
373 # --------------------------------
374
375 cat "${PAGES}" |
376 xsltproc \
377   --path "${TDIR}" \
378   --stringparam TITLE "${NAME}" \
379   --stringparam URL "${URL}" \
380   --stringparam DESCRIPTION "${NAME} news feed" \
381   "$(dirname "${0}")/rss20.xsl" - >"${ODIR}/index.rss"
382
383 # ------------------------------
384 echo "Copying static content..."
385 # ------------------------------
386
387 cp -au "${IDIR}/static/"* "${ODIR}/"
388
389 # ------------------------------
390 echo "Copying gallery images..."
391 # ------------------------------
392
393 mkdir -p "${ODIR}/g"
394 for g in "${IDIR}/gallery/"*
395 do
396   cp -au "${g}/" "${ODIR}/g/"
397 done
398
399 # -----------------------------------
400 echo "Updating gallery thumbnails..."
401 # -----------------------------------
402
403 for i in "${ODIR}/g/"*"/"*
404 do
405   if [[ ! ( "${i}" =~ "_thumb.jpg" ) ]]
406   then
407     if   [[ "${i}" =~ ".jpg" ]]
408     then
409       if [[ "${i/%.jpg/_thumb.jpg}" -ot "${i}" ]]
410       then
411         convert -resize "${THUMB}" "${i}" "${i/%.jpg/_thumb.jpg}"
412       fi
413     elif [[ "${i}" =~ ".png" ]]
414     then
415       if [[ "${i/%.png/_thumb.jpg}" -ot "${i}" ]]
416       then
417         convert -resize "${THUMB}" "${i}" "${i/%.png/_thumb.jpg}"
418       fi
419     fi
420   fi
421 done
422
423 # ----------
424 echo "Done!"
425 # ----------