Commit | Line | Data |
---|---|---|
0324a0cf JM |
1 | #!/usr/bin/make -f |
2 | # Source: https://pedantic.software/git/blogit/ | |
3 | BLOG := $(MAKE) -f $(lastword $(MAKEFILE_LIST)) --no-print-directory | |
4 | ifneq ($(filter-out help,$(MAKECMDGOALS)),) | |
5 | include config | |
6 | endif | |
7 | ||
8 | # The following can be configured in config | |
f4fc716c JM |
9 | BLOG_DATE_FORMAT_INDEX ?= %d/%m/%Y |
10 | BLOG_DATE_FORMAT ?= %d/%m/%Y %X | |
0324a0cf JM |
11 | BLOG_TITLE ?= blog |
12 | BLOG_DESCRIPTION ?= blog | |
8dd9db16 | 13 | BLOG_AUTHOR ?= John Doe |
0324a0cf JM |
14 | BLOG_URL_ROOT ?= http://localhost/blog |
15 | BLOG_FEED_MAX ?= 20 | |
16 | BLOG_FEEDS ?= rss atom | |
17 | BLOG_SRC ?= articles | |
18 | ||
19 | ||
20 | .PHONY: help init build deploy clean | |
21 | ||
22 | ARTICLES = $(shell git ls-tree HEAD --name-only -- $(BLOG_SRC)/ 2>/dev/null) | |
23 | TAGFILES = $(patsubst $(BLOG_SRC)/%.md,tags/%,$(ARTICLES)) | |
24 | ||
25 | help: | |
26 | $(info blogit init|build|deploy|clean) | |
27 | ||
28 | init: | |
29 | mkdir -p $(BLOG_SRC) data templates | |
30 | printf '<!DOCTYPE html><html><head><title>$$TITLE</title></head><body>' > templates/header.html | |
31 | printf '</body></html>' > templates/footer.html | |
32 | printf '' > templates/index_header.html | |
33 | printf '<p>Tags:' > templates/tag_list_header.html | |
34 | printf '<a href="$$URL">$$NAME</a>' > templates/tag_entry.html | |
35 | printf ', ' > templates/tag_separator.html | |
36 | printf '</p>' > templates/tag_list_footer.html | |
37 | printf '<h2>Articles</h2><ul>' > templates/article_list_header.html | |
38 | printf '<li><a href="$$URL">$$DATE $$TITLE</a></li>' > templates/article_entry.html | |
39 | printf '' > templates/article_separator.html | |
40 | printf '</ul>' > templates/article_list_footer.html | |
41 | printf '' > templates/index_footer.html | |
42 | printf '' > templates/tag_index_header.html | |
43 | printf '' > templates/tag_index_footer.html | |
44 | printf '<h1>$$TITLE</h1>' > templates/article_header.html | |
45 | printf '' > templates/article_footer.html | |
46 | printf 'blog\n' > .git/info/exclude | |
47 | ||
48 | build: blog/index.html tagpages $(patsubst $(BLOG_SRC)/%.md,blog/%.html,$(ARTICLES)) $(patsubst %,blog/%.xml,$(BLOG_FEEDS)) | |
49 | ||
50 | deploy: build | |
51 | rsync -rLtvz $(BLOG_RSYNC_OPTS) blog/ data/ $(BLOG_REMOTE) | |
52 | ||
53 | clean: | |
54 | rm -rf blog tags | |
55 | ||
56 | config: | |
57 | printf 'BLOG_REMOTE:=%s\n' \ | |
58 | '$(shell printf "Blog remote (eg: host:/var/www/html): ">/dev/tty; head -n1)' \ | |
59 | > $@ | |
60 | ||
61 | tags/%: $(BLOG_SRC)/%.md | |
62 | mkdir -p tags | |
63 | grep -i '^; *tags:' "$<" | cut -d: -f2- | sed 's/ */\n/g' | sed '/^$$/d' | sort -u > $@ | |
64 | ||
65 | 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 | mkdir -p blog | |
67 | TITLE="$(BLOG_TITLE)"; \ | |
68 | export TITLE; \ | |
adfee06d JM |
69 | DESCRIPTION="$(BLOG_DESCRIPTION)"; \ |
70 | export DESCRIPTION; \ | |
8dd9db16 JM |
71 | AUTHOR="$(BLOG_AUTHOR)"; \ |
72 | export AUTHOR; \ | |
0324a0cf JM |
73 | envsubst < templates/header.html > $@; \ |
74 | envsubst < templates/index_header.html >> $@; \ | |
75 | envsubst < templates/tag_list_header.html >> $@; \ | |
76 | first=true; \ | |
77 | for t in $(shell cat $(TAGFILES) | sort -u); do \ | |
78 | "$$first" || envsubst < templates/tag_separator.html; \ | |
79 | NAME="$$t" \ | |
80 | URL="@$$t.html" \ | |
81 | envsubst < templates/tag_entry.html; \ | |
82 | first=false; \ | |
83 | done >> $@; \ | |
84 | envsubst < templates/tag_list_footer.html >> $@; \ | |
85 | envsubst < templates/article_list_header.html >> $@; \ | |
86 | first=true; \ | |
87 | for f in $(ARTICLES); do \ | |
88 | printf '%s ' "$$f"; \ | |
89 | git log --diff-filter=A --date="format:%s $(BLOG_DATE_FORMAT_INDEX)" --pretty=format:'%ad%n' -- "$$f"; \ | |
90 | done | sort -k2nr | cut -d" " -f1,3- | while IFS=" " read -r FILE DATE; do \ | |
91 | "$$first" || envsubst < templates/article_separator.html; \ | |
92 | URL="`printf '%s' "\$$FILE" | sed 's,^$(BLOG_SRC)/\(.*\).md,\1,'`.html" \ | |
93 | DATE="$$DATE" \ | |
94 | TITLE="`head -n1 "\$$FILE" | sed -e 's/^# //g'`" \ | |
95 | envsubst < templates/article_entry.html; \ | |
96 | first=false; \ | |
97 | done >> $@; \ | |
98 | envsubst < templates/article_list_footer.html >> $@; \ | |
99 | envsubst < templates/index_footer.html >> $@; \ | |
100 | envsubst < templates/footer.html >> $@; \ | |
101 | ||
102 | ||
103 | blog/tag/%.html: $(ARTICLES) $(addprefix templates/,$(addsuffix .html,header tag_header index_entry tag_footer footer)) | |
104 | ||
105 | .PHONY: tagpages | |
106 | tagpages: $(TAGFILES) | |
107 | +$(BLOG) $(patsubst %,blog/@%.html,$(shell cat $(TAGFILES) | sort -u)) | |
108 | ||
109 | 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)) | |
110 | mkdir -p blog | |
adfee06d | 111 | TITLE="$(BLOG_TITLE) - Articles tagged $*"; \ |
0324a0cf | 112 | TAGS="$*"; \ |
8dd9db16 JM |
113 | AUTHOR=""; \ |
114 | export AUTHOR; \ | |
0324a0cf JM |
115 | export TITLE; \ |
116 | export TAGS; \ | |
117 | envsubst < templates/header.html > $@; \ | |
118 | envsubst < templates/tag_index_header.html >> $@; \ | |
119 | envsubst < templates/article_list_header.html >> $@; \ | |
120 | first=true; \ | |
121 | for f in $(shell grep -FH '$*' $(TAGFILES) | sed 's,^tags/\([^:]*\):.*,$(BLOG_SRC)/\1.md,'); do \ | |
122 | printf '%s ' "$$f"; \ | |
123 | git log --diff-filter=A --date="format:%s $(BLOG_DATE_FORMAT_INDEX)" --pretty=format:'%ad%n' -- "$$f"; \ | |
124 | done | sort -k2nr | cut -d" " -f1,3- | while IFS=" " read -r FILE DATE; do \ | |
125 | "$$first" || envsubst < templates/article_separator.html; \ | |
126 | URL="`printf '%s' "\$$FILE" | sed 's,^$(BLOG_SRC)/\(.*\).md,\1,'`.html" \ | |
127 | DATE="$$DATE" \ | |
128 | TITLE="`head -n1 "\$$FILE" | sed -e 's/^# //g'`" \ | |
129 | envsubst < templates/article_entry.html; \ | |
130 | first=false; \ | |
131 | done >> $@; \ | |
132 | envsubst < templates/article_list_footer.html >> $@; \ | |
133 | envsubst < templates/tag_index_footer.html >> $@; \ | |
134 | envsubst < templates/footer.html >> $@; \ | |
135 | ||
136 | ||
137 | blog/%.html: $(BLOG_SRC)/%.md $(addprefix templates/,$(addsuffix .html,header article_header article_footer footer)) | |
138 | mkdir -p blog | |
adfee06d | 139 | TITLE=" $(BLOG_TITLE) - $(shell head -n1 $<)"; \ |
0324a0cf | 140 | export TITLE; \ |
8dd9db16 | 141 | AUTHOR="$(shell git log -n 1 --reverse --format="%an" -- "$<")"; \ |
0324a0cf JM |
142 | export AUTHOR; \ |
143 | DATE_POSTED="$(shell git log --diff-filter=A --date="format:$(BLOG_DATE_FORMAT)" --pretty=format:'%ad' -- "$<")"; \ | |
144 | export DATE_POSTED; \ | |
145 | DATE_EDITED="$(shell git log -n 1 --date="format:$(BLOG_DATE_FORMAT)" --pretty=format:'%ad' -- "$<")"; \ | |
146 | export DATE_EDITED; \ | |
147 | TAGS="$(shell grep -i '^; *tags:' "$<" | cut -d: -f2- | paste -sd ',')"; \ | |
148 | export TAGS; \ | |
8c9e33cd JM |
149 | DESCRIPTION="$(shell grep -i '^; *description:' "$<" | cut -d: -f2-)"; \ |
150 | export DESCRIPTION; \ | |
78738995 JM |
151 | OG_IMAGE="$(shell grep -i '^; *og_image:' "$<" | cut -d: -f2-)"; \ |
152 | export OG_IMAGE; \ | |
0324a0cf JM |
153 | envsubst < templates/header.html > $@; \ |
154 | envsubst < templates/article_header.html >> $@; \ | |
155 | sed -e 1d \ | |
156 | -e '/^;/d' \ | |
157 | -e 's/&/\&/g' \ | |
158 | -e 's/</\</g' \ | |
159 | -e 's/>/\>/g' \ | |
160 | -e '/^```$$/{s,.*,,;x;p;/^<\/code>/d;s,.*,<pre><code>,;bT}' \ | |
161 | -e 'x;/<\/code>/{x;s,\$$,\$,g;$$G;p;d};x' \ | |
162 | -e 's,\\\$$,\$,g' \ | |
163 | -e '/^####/{s,^####,<h4>,;s,$$,</h4>,;H;s,.*,,;x;p;d}' \ | |
164 | -e '/^###/{s,^###,<h3>,;s,$$,</h3>,;H;s,.*,,;x;p;d}' \ | |
165 | -e '/^##/{s,^##,<h2>,;s,$$,</h2>,;H;s,.*,,;x;p;d}' \ | |
166 | -e '/^#/{s,^#,<h1>,;s,$$,</h1>,;H;s,.*,,;x;p;d}' \ | |
167 | -e 's,`\([^`]*\)`,<code>\1</code>,g' \ | |
168 | -e 's,\*\*\(\([^*<>][^*<>]*\*\?\)*\)\*\*,<b>\1</b>,g' \ | |
169 | -e 's,\*\([^*<>][^*<>]*\)\*,<i>\1</i>,g' \ | |
170 | -e 's,!\[\([^]]*\)\](\([^)]*\)),<img src="\2" alt="\1"/>,g' \ | |
171 | -e 's,\[\([^]]*\)\](\([^)]*\)),<a href="\2">\1</a>,g' \ | |
172 | -e '/^- /{s,^- ,<li>,;s,$$,</li>,;x;/^<\/ul>/{x;bL};p;s,.*,<ul>,;bT}' \ | |
173 | -e '/^[1-9][0-9]*\. /{s,^[0-9]*\. ,<li>,;s,$$,</li>,;x;/^<\/ol>/{x;bL};p;s,.*,<ol>,;bT}' \ | |
174 | -e '/^$$/{x;/^$$/d;p;d}' \ | |
175 | -e 'x;/^$$/{s,.*,<p>,;bT};x' \ | |
176 | -e ':L;$$G;p;d' \ | |
177 | -e ':T;p;:t;s,<\([^/>][^>]*\)>\(\(<[^/>][^>]*>\)*\),\2</\1>,;/<[^\/>]/bt;x;/^$$/{$${x;p};d};bL' \ | |
178 | "$<" | envsubst >> $@; \ | |
179 | envsubst < templates/article_footer.html >> $@; \ | |
180 | envsubst < templates/footer.html >> $@; \ | |
181 | ||
182 | blog/rss.xml: $(ARTICLES) | |
183 | 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' \ | |
184 | "$(BLOG_TITLE)" "$(BLOG_URL_ROOT)" "$(BLOG_DESCRIPTION)" > $@ | |
185 | for f in $(ARTICLES); do \ | |
186 | printf '%s ' "$$f"; \ | |
187 | git log --diff-filter=A --date="format:%s %a, %d %b %Y %H:%M:%S %z" --pretty=format:'%ad%n' -- "$$f"; \ | |
188 | done | sort -k2nr | head -n $(BLOG_FEED_MAX) | cut -d" " -f1,3- | while IFS=" " read -r FILE DATE; do \ | |
189 | 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' \ | |
a9f6852b | 190 | "`head -n 1 $$FILE | sed 's/&/&/'`" \ |
0324a0cf JM |
191 | "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \ |
192 | "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \ | |
193 | "$$DATE" \ | |
7f10ed74 | 194 | "`cat "$$FILE" | grep ";description:" | cut -d: -f2-`"; \ |
0324a0cf JM |
195 | done >> $@ |
196 | printf '</channel>\n</rss>\n' >> $@ | |
197 | ||
198 | blog/atom.xml: $(ARTICLES) | |
199 | 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' \ | |
200 | "$(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" > $@ | |
201 | for f in $(ARTICLES); do \ | |
202 | printf '%s ' "$$f"; \ | |
203 | git log --diff-filter=A --date="format:%s %Y-%m-%dT%H:%M:%SZ" --pretty=format:'%ad %aN%n' -- "$$f"; \ | |
204 | done | sort -k2nr | head -n $(BLOG_FEED_MAX) | cut -d" " -f1,3- | while IFS=" " read -r FILE DATE AUTHOR; do \ | |
205 | 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' \ | |
a9f6852b | 206 | "`head -n 1 $$FILE | sed 's/&/&/'`" \ |
0324a0cf JM |
207 | "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \ |
208 | "$(BLOG_URL_ROOT)/`basename $$FILE .md`.html" \ | |
209 | "$$DATE" \ | |
210 | "`git log -n 1 --date="format:%Y-%m-%dT%H:%M:%SZ" --pretty=format:'%ad' -- "$$FILE"`" \ | |
211 | "$$AUTHOR" \ | |
7f10ed74 | 212 | "`cat "$$FILE" | grep ";description:" | cut -d: -f2-`"; \ |
0324a0cf JM |
213 | done >> $@ |
214 | printf '</feed>\n' >> $@ |