ARTICLES=$(shell find articles -type f -name *.md)
RECENTARTICLES=$(shell code/recent-articles.sh)
GITCHANGEDARTICLES=$(shell git diff-tree --name-only -r HEAD | grep -e ^articles/)
IFRAMES=$(shell find iframes -type f,l) iframes/blogroll-nav.md
DOCUMENTS=$(shell find documents -type f)
STATICFILES=$(shell find static -type f,l)
IMAGES=$(shell find i -type f,l)
CODEFILES=$(shell find code -maxdepth 1 -type f -not -name "*.swp")
CODEINIFRAMES=$(shell cat articles/* | tr '<>' '\n' | grep -E '^iframe' | tr '"' '\n' | grep -E '^/code' | cut -d / -f 2-)

ARTICLEPAGES=$(ARTICLES:articles/%.md=public/%/index.html)
TMPARTICLES=$(ARTICLES:articles/%.md=tmp/articles/%/index.html)
DOCUMENTPAGES=$(DOCUMENTS:documents/%.md=public/%/index.html)
HTMLFRAGMENTS=$(ARTICLES:articles/%.md=tmp/htmlfragments/%.html)
RECENTHTMLFRAGMENTS=$(RECENTARTICLES:articles/%.md=tmp/htmlfragments/%.html)
RSSITEMS=$(ARTICLES:articles/%.md=tmp/rssitems/%)
LINKOUTS=$(ARTICLES:articles/%.md=tmp/linkouts/%)
PUBLICSTATICFILES=$(STATICFILES:static/%=public/%)
PUBLICIFRAMES=$(IFRAMES:iframes/%.md=public/%/index.html)
CODEIFRAMES=$(CODEINIFRAMES:code/%=tmp/iframes/code/%/index.html)
PUBLICIMAGES=$(IMAGES:i/%=public/i/%)
PUBLICCODE=$(CODEFILES:code/%=public/code/%)

all : basics feeds misc pages search
	find . -name *.bak -mmin +14 -delete
	find . -name *.swp -mmin +14 -delete

# feeds and maps (welcome robots) Can depend on pages.
feeds : public/feed.xml public/sitemap.xml public/sitemap.txt public/changes.xml

# Stuff that is needed by pages to preview correctly
basics : $(PUBLICIMAGES) $(PUBLICSTATICFILES) $(PUBLICCODE) $(CODEIFRAMES) public/code/Makefile public/robots.txt public/rss-subs.svg

# Extra stuff that needs to be deployed but not needed to rebuild a page
misc : public/favorites.txt public/outlinks.txt public/.well-known/myterms.json

# HTML pages
pages : $(ARTICLEPAGES) $(DOCUMENTPAGES) public/index.html public/all/index.html

# Preview files
previewpages : $(ARTICLEPAGES) $(DOCUMENTPAGES) basics

search : public/pagefind/pagefind-entry.json public/pagefind/pagefind-ui.js

blog.pws :
	echo "personal_ws-1.1 en 0" > $@

spell : $(ARTICLES) $(DOCUMENTS) blog.pws
	$(foreach c,$(ARTICLES) $(DOCUMENTS), aspell \
	--personal=./blog.pws check $(c);)

public/rss-subs.svg : code/get-rss $(ARTICLES)
	code/get-rss articles > $@

#begin search stuff
public/pagefind/pagefind-entry.json : $(TMPARTICLES) code/noindex public/404/index.html
	code/noindex public/404/index.html
	make tmp/articles/404/index.html
	rm -rf tmp/articles/pagefind
	pagefind --site tmp/articles
	rm -rf public/pagefind
	mv tmp/articles/pagefind public

public/pagefind/pagefind-ui.js : public/pagefind/pagefind-entry.json

# tmp copy of articles for building search index
tmp/articles/%/index.html : public/%/index.html tmp/framed/%.html articles/%.md
	install -m 644 -D $< $@
# end search stuff

iframes/blogroll-nav.md : code/blogroll static/blogroll.opml
	code/blogroll > $@

tmp/iframes/code/%/index.html : code/% code/codeiframe
	mkdir -p $(shell dirname $@)
	code/codeiframe $< $@

public/.well-known/myterms.json : public/web-site-user-agreement/index.html code/toswriter
	mkdir -p $(shell dirname $@)
	code/toswriter

public/sitemap.txt : $(ARTICLES) code/make-sitemap.sh
	mkdir -p public
	code/make-sitemap.sh

public/sitemap.xml : $(ARTICLEPAGES) public/index.html code/xmlwriter
	code/xmlwriter --format=sitemap public > $@

public/feed.xml : $(ARTICLEPAGES) public/index.html code/xmlwriter
	code/xmlwriter --format=rss --fulltext public/ > $@

public/changes.xml : $(ARTICLEPAGES) public/index.html code/xmlwriter
	code/xmlwriter --format=rss --mod \
	--title="Recently changed pages on blog.zgp.org" \
	--description="This feed includes new and changed pages. See https://blog.zgp.org/feed/ for new posts." \
	public > $@

tmp/tmplinks.txt : $(ARTICLEPAGES) $(DOCUMENTPAGES)
	mkdir -p $(shell dirname $@)
	cat articles/* documents/* | tr '()' '\n' | grep ^http | sort -u > $@

public/outlinks.txt : $(ARTICLEPAGES) $(DOCUMENTPAGES) code/outlinks
	code/outlinks urls public > $@

public/favorites.txt : public/all/index.html code/favorites
	code/favorites public/all > $@

public/% : static/%
	install -m 644 -D $< $@

public/i/% : i/%
	install -m 644 -D $< $@
	chmod a+r $@

public/code/% : code/%
	mkdir -p public/code
	cp $< $@

public/code/Makefile : Makefile
	cp $< $@

tmp/pagetemplate.html : templates/begin.html templates/end.html templates/article.html
	mkdir -p tmp
	cat templates/begin.html templates/article.html templates/end.html > $@

# Beginning of the home and "all" pages
tmp/allhead.html : templates/begin.html
	mkdir -p tmp
	touch tmp/blank.md
	pandoc --template templates/begin.html --to=html5+smart --css=/style.css \
	-V pagetitle="blog: Don Marti" \
	-V description="Personal blog for Don Marti" \
	-o $@ $<
	rm -f tmp/blank.md

# End of the home and "all" pages
tmp/allend.html : templates/end.html tmp/nav.html
	touch tmp/blank.md
	pandoc --template templates/end.html --to=html5+smart --css=/style.css \
	-V pagetitle="blog: Don Marti" \
	-V nav="$(shell cat tmp/nav.html)" \
	-o $@ $<
	rm -f tmp/blank.md

tmp/htmlfragments/%.html : public/%/index.html articles/%.md code/extract-element
	mkdir -p tmp/htmlfragments
	code/extract-element $< $@ article
	echo -ne '\0' >> $@

tmp/linkouts/% : articles/%.md
	mkdir -p tmp/linkouts
	tr '()' '\n' < $< | grep ^https://blog.zgp.org/ | sort -u | cut -d / -f 4 > $@

#
# Begin home page stuff
#

# Home page framed
tmp/homepagecontent.html : $(RECENTHTMLFRAGMENTS) code/rm-unmakeable
	cat $(RECENTHTMLFRAGMENTS) | sort -zr | head -z > $@

tmp/framed/index.html : tmp/homepagecontent.html tmp/allhead.html tmp/allend.html
	mkdir -p $(shell dirname $@)
	cat tmp/allhead.html tmp/homepagecontent.html tmp/allend.html | tr -d "\0" > $@

# Blank nav element for blank similar links on home page
public/index/similar/index.html :
	mkdir -p $(shell dirname $@)
	cp static/emptynav.html $@

# Blank nav element for blank similar links on all page
public/all/index/similar/index.html :
	mkdir -p $(shell dirname $@)
	cp static/emptynav.html $@

# Home page
public/index.html : tmp/framed/index.html code/deframe public/index/similar/index.html
	code/deframe $< $@

tmp/allcontent.html : $(HTMLFRAGMENTS) code/rm-unmakeable
	code/rm-unmakeable
	cat tmp/htmlfragments/*.html | sort -zr > $@

tmp/framed/all/index.html : tmp/allcontent.html tmp/allhead.html tmp/allend.html
	mkdir -p $(shell dirname $@)
	cat tmp/allhead.html tmp/allcontent.html tmp/allend.html | tr -d "\0" > $@

public/all/index.html : tmp/framed/all/index.html code/deframe code/noindex
	mkdir -p $(shell dirname $@)
	code/deframe $< $@
	code/linkcheck delete $@
	code/noindex $@ || make $@
	html5validator --ignore='not allowed on element "button" at this point' $@

# Right column nav
tmp/nav.html : public/toc/index.html code/extract-element
	mkdir -p $(shell dirname $@)
	code/extract-element $< $@ nav

# regular articles (pre-build of temporary framed version)
tmp/framed/%.html : articles/%.md code/blogdate code/gitdate.sh tmp/pagetemplate.html
	mkdir -p $(shell dirname $@)
	pandoc 	-V blog_date="$(shell code/blogdate $<)" \
		-V modified_time="$(shell code/gitdate.sh $<)" \
		-V slug=$(shell basename -s .md $<) \
		-V slug_prefix="https://blog.zgp.org/" \
		-V slug_suffix="/" \
		--section-divs \
		--lua-filter code/article.lua \
		--template tmp/pagetemplate.html --to=html5+smart --css=/style.css \
		-o $@ $<

public/%/similar/index.html : articles/%.md code/similar_links tmp/linkouts/%
	mkdir -p $(shell dirname $@)
	code/similar_links $< > $@

# articles (populate frames with content if available)
public/%/index.html : tmp/framed/%.html articles/%.md public/%/similar/index.html code/deframe
	code/deframe $< $@
	code/linkcheck delete $@

# documents
tmp/framed/%.html : documents/%.md code/blogdate templates/document.html
	mkdir -p $(shell dirname $@)
	pandoc 	-V blog_date="$(shell code/blogdate $<)" \
		-V slug=$(shell basename -s .md $<) \
		-V slug_prefix="/all/#" \
		-V slug_suffix="" \
		--section-divs \
		--template ./templates/document.html --to=html5+smart --css=/style.css \
		-o $@ $<

# documents (populate frames with content if available)
public/%/index.html : tmp/framed/%.html documents/%.md code/deframe
	mkdir -p $(shell dirname $@)
	code/deframe $< $@
	code/linkcheck delete $@

# iframes
public/%/index.html : iframes/%.md templates/iframe.html code/linktop.lua
	mkdir -p $(shell dirname $@)
	pandoc 	--template ./templates/iframe.html --to=html5+smart --css=/style.css \
		--section-divs \
		--lua-filter code/linktop.lua \
		-o $@ $<

referers : tmp/referers.txt tmp/zreferers.txt
	echo | code/note-referers.sh | less

tmp/newreferers.txt :
	mkdir -p tmp
	ssh blog.zgp.org cat /var/log/apache2/blog-access.log | \
	cut -d ' ' -f 11 | grep -Ev '//blog.zgp.org' > $@

tmp/zreferers.txt :
	mkdir -p tmp
	ssh blog.zgp.org zcat /var/log/apache2/blog-access.log.?.gz | \
	cut -d ' ' -f 11 | grep -Ev '//blog.zgp.org' > $@

tmp/referers.txt : tmp/newreferers.txt tmp/zreferers.txt  code/note-referers.sh
	sort -u tmp/newreferers.txt | code/note-referers.sh > /dev/null
	sort -u tmp/zreferers.txt | code/note-referers.sh > /dev/null
	cat tmp/newreferers.txt tmp/zreferers.txt | \
	sort | uniq -c | sort -nr > $@

data/recentlog :
	ssh blog.zgp.org cat /var/log/apache2/blog-access.log.1 > $@
	ssh blog.zgp.org cat /var/log/apache2/blog-access.log >> $@

data/rss-subscribers : data/recentlog
	code/count-subs < $< > $@

deploy : tidy synced
	code/deploy.sh
	[ -e tmp/404.txt ] && head -n 4 tmp/404.txt

# update AI crawlers blocking list from darkvisitors.com
data/robots.txt :
	mkdir -p $(shell dirname $@)
	curl -X POST "https://api.darkvisitors.com/robots-txts" \
		-H "Authorization: Bearer $(shell pass darkvisitors-token)" \
		-H "Content-Type: application/json" \
		-d '{"agent_types": ["AI Data Scraper", "AI Assistant", "Undocumented AI Agent", "AI Search Crawler"], "disallow": "/"}' \
	> $@

# The real robots.txt is built from the local lines under conf with the
# darkvisitors.com lines added
public/robots.txt : conf/robots.txt data/robots.txt public
	cat conf/robots.txt data/robots.txt > $@

# List of 404s to fix
tmp/404.txt :
	mkdir -p tmp
	ssh blog.zgp.org grep 404 /var/log/apache2/blog-access.log | \
	grep -v semrush | cut -d ' ' -f 7,9 | sort | uniq -c | sort -nr | grep 404 \
	> $@ || touch $@

tmp/newlinks.txt :
	ssh rapids.aloodo.org ./unblogged.py > $@

fresh :
	mkdir -p tmp
	ssh rapids.aloodo.org ./rss https://blog.zgp.org/feed.xml || true
	ssh blog.zgp.org true && find data/robots.txt -mtime +29 -delete || true
	ssh blog.zgp.org true && find data/recentlog -mmin +239 -delete || true
	ssh blog.zgp.org true && find data/rss-subscribers -mmin +239 -delete || true
	find tmp/404.txt -mmin +359 -delete || true
	find tmp/zreferers.txt -mmin +359 -delete || true
	touch tmp/newreferers.txt
	touch tmp/zreferers.txt
	cat tmp/newreferers.txt >> tmp/zreferers.txt
	rm -f tmp/newreferers.txt

tidy :
	code/rm-unmakeable || make tidy

synced : data/robots.txt tmp/404.txt tmp/referers.txt data/rss-subscribers
	code/gitcow.sh

cleanhome :
	rm -f tmp/allmd.md
	rm -f tmp/framed/index.html
	rm -f tmp/framed/all/index.html
	rm -f tmp/allcontent.html
	rm -f tmp/homepagecontent.html
	rm -f public/index.html
	rm -f public/all/index.html
	rm -f public/changes.xml
	rm -f public/feed.xml
	rm -f public/outlinks.txt
	rm -rf public/pagefind
	rm -f public/sitemap.txt
	rm -f public/sitemap.xml
	rm -rf tmp/articles/pagefind
	rm -f tmp/feed.xml
	find . -empty -type d -delete

clean :
	rm -rf iframes/blogroll-nav.md public tmp || make clean

# List what hooks need to be present
hooks : .git/hooks/post-commit

# Simple hook that just runs make followed by its own name
.git/hooks/% : Makefile
	echo "#!/bin/sh" > $@
	echo "make `basename $@` 2>/dev/null" >> $@
	chmod 755 $@

post-commit:
	touch -c . $(GITCHANGEDARTICLES)

# try to remove broken partial files on error
.DELETE_ON_ERROR :

.NOTPARALLEL: feeds misc search

.PHONY : all basics clean cleanhome deploy feeds fresh hooks misc pages previewpages post-commit referers search synced tidy

.PRECIOUS : public/%/similar/index.html tmp/articles/% tmp/framed/%.html tmp/htmlfragments/%.html tmp/linkouts/%
