2 # Source: https://pedantic.software/git/blogit/
3 BLOG
:= $(MAKE
) -f
$(lastword
$(MAKEFILE_LIST
)) --no-print-directory
4 ifneq ($(filter-out help
,$(MAKECMDGOALS
)),)
8 # The following can be configured in config
9 BLOG_DATE_FORMAT_INDEX ?
= %x
10 BLOG_DATE_FORMAT ?
= %x
%X
12 BLOG_DESCRIPTION ?
= blog
13 BLOG_URL_ROOT ?
= http
://localhost
/blog
15 BLOG_FEEDS ?
= rss atom
19 .PHONY
: help init build deploy
clean
21 ARTICLES
= $(shell git ls-tree HEAD
--name-only
-- $(BLOG_SRC
)/ 2>/dev
/null
)
22 TAGFILES
= $(patsubst $(BLOG_SRC
)/%.md
,tags/%,$(ARTICLES
))
25 $(info blogit init|build|deploy|
clean)
28 mkdir
-p
$(BLOG_SRC
) data templates
29 printf
'<!DOCTYPE html><html><head><title>$$TITLE</title></head><body>' > templates
/header.html
30 printf
'</body></html>' > templates
/footer.html
31 printf
'' > templates
/index_header.html
32 printf
'<p>Tags:' > templates
/tag_list_header.html
33 printf
'<a href="$$URL">$$NAME</a>' > templates
/tag_entry.html
34 printf
', ' > templates
/tag_separator.html
35 printf
'</p>' > templates
/tag_list_footer.html
36 printf
'<h2>Articles</h2><ul>' > templates
/article_list_header.html
37 printf
'<li><a href="$$URL">$$DATE $$TITLE</a></li>' > templates
/article_entry.html
38 printf
'' > templates
/article_separator.html
39 printf
'</ul>' > templates
/article_list_footer.html
40 printf
'' > templates
/index_footer.html
41 printf
'' > templates
/tag_index_header.html
42 printf
'' > templates
/tag_index_footer.html
43 printf
'<h1>$$TITLE</h1>' > templates
/article_header.html
44 printf
'' > templates
/article_footer.html
45 printf
'blog\n' > .git
/info/exclude
47 build
: blog
/index.html tagpages
$(patsubst $(BLOG_SRC
)/%.md
,blog
/%.html
,$(ARTICLES
)) $(patsubst %,blog
/%.xml
,$(BLOG_FEEDS
))
50 rsync
-rLtvz
$(BLOG_RSYNC_OPTS
) blog
/ data
/ $(BLOG_REMOTE
)
56 printf
'BLOG_REMOTE:=%s\n' \
57 '$(shell printf "Blog remote (eg: host:/var/www/html): ">/dev/tty; head -n1)' \
60 tags/%: $(BLOG_SRC
)/%.md
62 grep
-i
'^; *tags:' "$<" | cut
-d
: -f2- | sed
's/ */\n/g' | sed
'/^$$/d' |
sort -u
> $@
64 blog
/index.html
: $(ARTICLES
) $(TAGFILES
) $(addprefix templates
/,$(addsuffix .html
,header index_header tag_list_header tag_entry tag_separator tag_list_footer article_list_header article_entry article_separator article_list_footer index_footer footer
))
66 TITLE
="$(BLOG_TITLE)"; \
68 DESCRIPTION
="$(BLOG_DESCRIPTION)"; \
70 envsubst
< templates
/header.html
> $@
; \
71 envsubst
< templates
/index_header.html
>> $@
; \
72 envsubst
< templates
/tag_list_header.html
>> $@
; \
74 for t in
$(shell cat
$(TAGFILES
) |
sort -u
); do \
75 "$$first" || envsubst
< templates
/tag_separator.html
; \
78 envsubst
< templates
/tag_entry.html
; \
81 envsubst
< templates
/tag_list_footer.html
>> $@
; \
82 envsubst
< templates
/article_list_header.html
>> $@
; \
84 for f in
$(ARTICLES
); do \
86 git log
--diff-filter
=A
--date
="format:%s $(BLOG_DATE_FORMAT_INDEX)" --pretty
=format
:'%ad%n' -- "$$f"; \
87 done |
sort -k2nr | cut
-d
" " -f1
,3- | while IFS
=" " read
-r FILE DATE
; do \
88 "$$first" || envsubst
< templates
/article_separator.html
; \
89 URL
="`printf '%s' "\
$$FILE" | sed 's,^$(BLOG_SRC)/\(.*\).md,\1,'`.html" \
91 TITLE
="`head -n1 "\
$$FILE" | sed -e 's/^# //g'`" \
92 envsubst
< templates
/article_entry.html
; \
95 envsubst
< templates
/article_list_footer.html
>> $@
; \
96 envsubst
< templates
/index_footer.html
>> $@
; \
97 envsubst
< templates
/footer.html
>> $@
; \
100 blog
/tag
/%.html
: $(ARTICLES
) $(addprefix templates
/,$(addsuffix .html
,header tag_header index_entry tag_footer footer
))
103 tagpages
: $(TAGFILES
)
104 +$(BLOG
) $(patsubst %,blog
/@
%.html
,$(shell cat
$(TAGFILES
) |
sort -u
))
106 blog
/@
%.html
: $(TAGFILES
) $(addprefix templates
/,$(addsuffix .html
,header tag_index_header tag_list_header tag_entry tag_separator tag_list_footer article_list_header article_entry article_separator article_list_footer tag_index_footer footer
))
108 TITLE
="$(BLOG_TITLE) - Articles tagged $*"; \
112 envsubst
< templates
/header.html
> $@
; \
113 envsubst
< templates
/tag_index_header.html
>> $@
; \
114 envsubst
< templates
/article_list_header.html
>> $@
; \
116 for f in
$(shell grep
-FH
'$*' $(TAGFILES
) | sed
's,^tags/\([^:]*\):.*,$(BLOG_SRC)/\1.md,'); do \
117 printf
'%s ' "$$f"; \
118 git log
--diff-filter
=A
--date
="format:%s $(BLOG_DATE_FORMAT_INDEX)" --pretty
=format
:'%ad%n' -- "$$f"; \
119 done |
sort -k2nr | cut
-d
" " -f1
,3- | while IFS
=" " read
-r FILE DATE
; do \
120 "$$first" || envsubst
< templates
/article_separator.html
; \
121 URL
="`printf '%s' "\
$$FILE" | sed 's,^$(BLOG_SRC)/\(.*\).md,\1,'`.html" \
123 TITLE
="`head -n1 "\
$$FILE" | sed -e 's/^# //g'`" \
124 envsubst
< templates
/article_entry.html
; \
127 envsubst
< templates
/article_list_footer.html
>> $@
; \
128 envsubst
< templates
/tag_index_footer.html
>> $@
; \
129 envsubst
< templates
/footer.html
>> $@
; \
132 blog
/%.html
: $(BLOG_SRC
)/%.md
$(addprefix templates
/,$(addsuffix .html
,header article_header article_footer footer
))
134 TITLE
=" $(BLOG_TITLE) - $(shell head -n1 $<)"; \
136 AUTHOR
="$(shell git log -n 1 --reverse --format="%cn
" -- "$<")"; \
138 DATE_POSTED
="$(shell git log --diff-filter=A --date="format
:$(BLOG_DATE_FORMAT
)" --pretty=format:'%ad' -- "$<")"; \
139 export DATE_POSTED
; \
140 DATE_EDITED
="$(shell git log -n 1 --date="format
:$(BLOG_DATE_FORMAT
)" --pretty=format:'%ad' -- "$<")"; \
141 export DATE_EDITED
; \
142 TAGS
="$(shell grep -i '^; *tags:' "$<" | cut -d: -f2- | paste -sd ',')"; \
144 DESCRIPTION
="$(shell grep -i '^; *description:' "$<" | cut -d: -f2-)"; \
145 export DESCRIPTION
; \
146 OG_IMAGE
="$(shell grep -i '^; *og_image:' "$<" | cut -d: -f2-)"; \
148 envsubst
< templates
/header.html
> $@
; \
149 envsubst
< templates
/article_header.html
>> $@
; \
155 -e
'/^```$$/{s,.*,,;x;p;/^<\/code>/d;s,.*,<pre><code>,;bT}' \
156 -e
'x;/<\/code>/{x;s,\$$,\$,g;$$G;p;d};x' \
157 -e
's,\\\$$,\$,g' \
158 -e
'/^####/{s,^####,<h4>,;s,$$,</h4>,;H;s,.*,,;x;p;d}' \
159 -e
'/^###/{s,^###,<h3>,;s,$$,</h3>,;H;s,.*,,;x;p;d}' \
160 -e
'/^##/{s,^##,<h2>,;s,$$,</h2>,;H;s,.*,,;x;p;d}' \
161 -e
'/^#/{s,^#,<h1>,;s,$$,</h1>,;H;s,.*,,;x;p;d}' \
162 -e
's,`\([^`]*\)`,<code>\1</code>,g' \
163 -e
's,\*\*\(\([^*<>][^*<>]*\*\?\)*\)\*\*,<b>\1</b>,g' \
164 -e
's,\*\([^*<>][^*<>]*\)\*,<i>\1</i>,g' \
165 -e
's,!\[\([^]]*\)\](\([^)]*\)),<img src="\2" alt="\1"/>,g' \
166 -e
's,\[\([^]]*\)\](\([^)]*\)),<a href="\2">\1</a>,g' \
167 -e
'/^- /{s,^- ,<li>,;s,$$,</li>,;x;/^<\/ul>/{x;bL};p;s,.*,<ul>,;bT}' \
168 -e
'/^[1-9][0-9]*\. /{s,^[0-9]*\. ,<li>,;s,$$,</li>,;x;/^<\/ol>/{x;bL};p;s,.*,<ol>,;bT}' \
169 -e
'/^$$/{x;/^$$/d;p;d}' \
170 -e
'x;/^$$/{s,.*,<p>,;bT};x' \
172 -e
':T;p;:t;s,<\([^/>][^>]*\)>\(\(<[^/>][^>]*>\)*\),\2</\1>,;/<[^\/>]/bt;x;/^$$/{$${x;p};d};bL' \
173 "$<" | envsubst
>> $@
; \
174 envsubst
< templates
/article_footer.html
>> $@
; \
175 envsubst
< templates
/footer.html
>> $@
; \
177 blog
/rss.xml
: $(ARTICLES
)
178 printf
'<?xml version="1.0" encoding="UTF-8"?>\n<rss version="2.0">\n<channel>\n<title>%s</title>\n<link>%s</link>\n<description>%s</description>\n' \
179 "$(BLOG_TITLE)" "$(BLOG_URL_ROOT)" "$(BLOG_DESCRIPTION)" > $@
180 for f in
$(ARTICLES
); do \
181 printf
'%s ' "$$f"; \
182 git log
--diff-filter
=A
--date
="format:%s %a, %d %b %Y %H:%M:%S %z" --pretty
=format
:'%ad%n' -- "$$f"; \
183 done |
sort -k2nr | head
-n
$(BLOG_FEED_MAX
) | cut
-d
" " -f1
,3- | while IFS
=" " read
-r FILE DATE
; do \
184 printf
'<item>\n<title>%s</title>\n<link>%s</link>\n<guid>%s</guid>\n<pubDate>%s</pubDate>\n<description>%s</description>\n</item>\n' \
185 "`head -n 1 $$FILE | sed 's/&/&/'`" \
186 "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \
187 "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \
189 "`cat "$$FILE" | grep ";description
:" | cut -d: -f2-`"; \
191 printf
'</channel>\n</rss>\n' >> $@
193 blog
/atom.xml
: $(ARTICLES
)
194 printf
'<?xml version="1.0" encoding="UTF-8"?>\n<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">\n<title type="text">%s</title>\n<subtitle type="text">%s</subtitle>\n<updated>%s</updated>\n<link rel="alternate" type="text/html" href="%s"/>\n<id>%s</id>\n<link rel="self" type="application/atom+xml" href="%s"/>\n' \
195 "$(BLOG_TITLE)" "$(BLOG_DESCRIPTION)" "$(shell date +%Y-%m-%dT%H:%M:%SZ)" "$(BLOG_URL_ROOT)" "$(BLOG_URL_ROOT)/atom.xml" "$(BLOG_URL_ROOT)/atom.xml" > $@
196 for f in
$(ARTICLES
); do \
197 printf
'%s ' "$$f"; \
198 git log
--diff-filter
=A
--date
="format:%s %Y-%m-%dT%H:%M:%SZ" --pretty
=format
:'%ad %aN%n' -- "$$f"; \
199 done |
sort -k2nr | head
-n
$(BLOG_FEED_MAX
) | cut
-d
" " -f1
,3- | while IFS
=" " read
-r FILE DATE AUTHOR
; do \
200 printf
'<entry>\n<title type="text">%s</title>\n<link rel="alternate" type="text/html" href="%s"/>\n<id>%s</id>\n<published>%s</published>\n<updated>%s</updated>\n<author><name>%s</name></author>\n<summary type="text">%s</summary>\n</entry>\n' \
201 "`head -n 1 $$FILE | sed 's/&/&/'`" \
202 "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \
203 "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \
205 "`git log -n 1 --date="format
:%Y-
%m-
%dT
%H
:%M
:%SZ
" --pretty=format:'%ad' -- "$$FILE"`" \
207 "`cat "$$FILE" | grep ";description
:" | cut -d: -f2-`"; \
209 printf
'</feed>\n' >> $@