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 envsubst
< templates
/header.html
> $@
; \
69 envsubst
< templates
/index_header.html
>> $@
; \
70 envsubst
< templates
/tag_list_header.html
>> $@
; \
72 for t in
$(shell cat
$(TAGFILES
) |
sort -u
); do \
73 "$$first" || envsubst
< templates
/tag_separator.html
; \
76 envsubst
< templates
/tag_entry.html
; \
79 envsubst
< templates
/tag_list_footer.html
>> $@
; \
80 envsubst
< templates
/article_list_header.html
>> $@
; \
82 for f in
$(ARTICLES
); do \
84 git log
--diff-filter
=A
--date
="format:%s $(BLOG_DATE_FORMAT_INDEX)" --pretty
=format
:'%ad%n' -- "$$f"; \
85 done |
sort -k2nr | cut
-d
" " -f1
,3- | while IFS
=" " read
-r FILE DATE
; do \
86 "$$first" || envsubst
< templates
/article_separator.html
; \
87 URL
="`printf '%s' "\
$$FILE" | sed 's,^$(BLOG_SRC)/\(.*\).md,\1,'`.html" \
89 TITLE
="`head -n1 "\
$$FILE" | sed -e 's/^# //g'`" \
90 envsubst
< templates
/article_entry.html
; \
93 envsubst
< templates
/article_list_footer.html
>> $@
; \
94 envsubst
< templates
/index_footer.html
>> $@
; \
95 envsubst
< templates
/footer.html
>> $@
; \
98 blog
/tag
/%.html
: $(ARTICLES
) $(addprefix templates
/,$(addsuffix .html
,header tag_header index_entry tag_footer footer
))
101 tagpages
: $(TAGFILES
)
102 +$(BLOG
) $(patsubst %,blog
/@
%.html
,$(shell cat
$(TAGFILES
) |
sort -u
))
104 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
))
106 TITLE
="Articles tagged $*"; \
110 envsubst
< templates
/header.html
> $@
; \
111 envsubst
< templates
/tag_index_header.html
>> $@
; \
112 envsubst
< templates
/article_list_header.html
>> $@
; \
114 for f in
$(shell grep
-FH
'$*' $(TAGFILES
) | sed
's,^tags/\([^:]*\):.*,$(BLOG_SRC)/\1.md,'); do \
115 printf
'%s ' "$$f"; \
116 git log
--diff-filter
=A
--date
="format:%s $(BLOG_DATE_FORMAT_INDEX)" --pretty
=format
:'%ad%n' -- "$$f"; \
117 done |
sort -k2nr | cut
-d
" " -f1
,3- | while IFS
=" " read
-r FILE DATE
; do \
118 "$$first" || envsubst
< templates
/article_separator.html
; \
119 URL
="`printf '%s' "\
$$FILE" | sed 's,^$(BLOG_SRC)/\(.*\).md,\1,'`.html" \
121 TITLE
="`head -n1 "\
$$FILE" | sed -e 's/^# //g'`" \
122 envsubst
< templates
/article_entry.html
; \
125 envsubst
< templates
/article_list_footer.html
>> $@
; \
126 envsubst
< templates
/tag_index_footer.html
>> $@
; \
127 envsubst
< templates
/footer.html
>> $@
; \
130 blog
/%.html
: $(BLOG_SRC
)/%.md
$(addprefix templates
/,$(addsuffix .html
,header article_header article_footer footer
))
132 TITLE
="$(shell head -n1 $<)"; \
134 AUTHOR
="$(shell git log -n 1 --reverse --format="%cn
" -- "$<")"; \
136 DATE_POSTED
="$(shell git log --diff-filter=A --date="format
:$(BLOG_DATE_FORMAT
)" --pretty=format:'%ad' -- "$<")"; \
137 export DATE_POSTED
; \
138 DATE_EDITED
="$(shell git log -n 1 --date="format
:$(BLOG_DATE_FORMAT
)" --pretty=format:'%ad' -- "$<")"; \
139 export DATE_EDITED
; \
140 TAGS
="$(shell grep -i '^; *tags:' "$<" | cut -d: -f2- | paste -sd ',')"; \
142 DESCRIPTION
="$(shell grep -i '^; *description:' "$<" | cut -d: -f2-)"; \
143 export DESCRIPTION
; \
144 OG_IMAGE
="$(shell grep -i '^; *og_image:' "$<" | cut -d: -f2-)"; \
146 envsubst
< templates
/header.html
> $@
; \
147 envsubst
< templates
/article_header.html
>> $@
; \
153 -e
'/^```$$/{s,.*,,;x;p;/^<\/code>/d;s,.*,<pre><code>,;bT}' \
154 -e
'x;/<\/code>/{x;s,\$$,\$,g;$$G;p;d};x' \
155 -e
's,\\\$$,\$,g' \
156 -e
'/^####/{s,^####,<h4>,;s,$$,</h4>,;H;s,.*,,;x;p;d}' \
157 -e
'/^###/{s,^###,<h3>,;s,$$,</h3>,;H;s,.*,,;x;p;d}' \
158 -e
'/^##/{s,^##,<h2>,;s,$$,</h2>,;H;s,.*,,;x;p;d}' \
159 -e
'/^#/{s,^#,<h1>,;s,$$,</h1>,;H;s,.*,,;x;p;d}' \
160 -e
's,`\([^`]*\)`,<code>\1</code>,g' \
161 -e
's,\*\*\(\([^*<>][^*<>]*\*\?\)*\)\*\*,<b>\1</b>,g' \
162 -e
's,\*\([^*<>][^*<>]*\)\*,<i>\1</i>,g' \
163 -e
's,!\[\([^]]*\)\](\([^)]*\)),<img src="\2" alt="\1"/>,g' \
164 -e
's,\[\([^]]*\)\](\([^)]*\)),<a href="\2">\1</a>,g' \
165 -e
'/^- /{s,^- ,<li>,;s,$$,</li>,;x;/^<\/ul>/{x;bL};p;s,.*,<ul>,;bT}' \
166 -e
'/^[1-9][0-9]*\. /{s,^[0-9]*\. ,<li>,;s,$$,</li>,;x;/^<\/ol>/{x;bL};p;s,.*,<ol>,;bT}' \
167 -e
'/^$$/{x;/^$$/d;p;d}' \
168 -e
'x;/^$$/{s,.*,<p>,;bT};x' \
170 -e
':T;p;:t;s,<\([^/>][^>]*\)>\(\(<[^/>][^>]*>\)*\),\2</\1>,;/<[^\/>]/bt;x;/^$$/{$${x;p};d};bL' \
171 "$<" | envsubst
>> $@
; \
172 envsubst
< templates
/article_footer.html
>> $@
; \
173 envsubst
< templates
/footer.html
>> $@
; \
175 blog
/rss.xml
: $(ARTICLES
)
176 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' \
177 "$(BLOG_TITLE)" "$(BLOG_URL_ROOT)" "$(BLOG_DESCRIPTION)" > $@
178 for f in
$(ARTICLES
); do \
179 printf
'%s ' "$$f"; \
180 git log
--diff-filter
=A
--date
="format:%s %a, %d %b %Y %H:%M:%S %z" --pretty
=format
:'%ad%n' -- "$$f"; \
181 done |
sort -k2nr | head
-n
$(BLOG_FEED_MAX
) | cut
-d
" " -f1
,3- | while IFS
=" " read
-r FILE DATE
; do \
182 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' \
183 "`head -n 1 $$FILE | sed 's/&/&/'`" \
184 "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \
185 "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \
187 "`cat "$$FILE" | grep ";description
:" | cut -d: -f2-`"; \
189 printf
'</channel>\n</rss>\n' >> $@
191 blog
/atom.xml
: $(ARTICLES
)
192 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' \
193 "$(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" > $@
194 for f in
$(ARTICLES
); do \
195 printf
'%s ' "$$f"; \
196 git log
--diff-filter
=A
--date
="format:%s %Y-%m-%dT%H:%M:%SZ" --pretty
=format
:'%ad %aN%n' -- "$$f"; \
197 done |
sort -k2nr | head
-n
$(BLOG_FEED_MAX
) | cut
-d
" " -f1
,3- | while IFS
=" " read
-r FILE DATE AUTHOR
; do \
198 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' \
199 "`head -n 1 $$FILE | sed 's/&/&/'`" \
200 "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \
201 "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \
203 "`git log -n 1 --date="format
:%Y-
%m-
%dT
%H
:%M
:%SZ
" --pretty=format:'%ad' -- "$$FILE"`" \
205 "`cat "$$FILE" | grep ";description
:" | cut -d: -f2-`"; \
207 printf
'</feed>\n' >> $@